]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/arm.md
re PR target/89434 (wrong code with -Og and __builtin_mul_overflow())
[thirdparty/gcc.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright (C) 1991-2019 Free Software Foundation, Inc.
3 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;; and Martin Simmons (@harleqn.co.uk).
5 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
6
7 ;; This file is part of GCC.
8
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
11 ;; by the Free Software Foundation; either version 3, or (at your
12 ;; option) any later version.
13
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.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3. If not see
21 ;; <http://www.gnu.org/licenses/>.
22
23 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
25 \f
26 ;;---------------------------------------------------------------------------
27 ;; Constants
28
29 ;; Register numbers -- All machine registers should be defined here
30 (define_constants
31 [(R0_REGNUM 0) ; First CORE register
32 (R1_REGNUM 1) ; Second CORE register
33 (R4_REGNUM 4) ; Fifth CORE register
34 (IP_REGNUM 12) ; Scratch register
35 (SP_REGNUM 13) ; Stack pointer
36 (LR_REGNUM 14) ; Return address register
37 (PC_REGNUM 15) ; Program counter
38 (LAST_ARM_REGNUM 15) ;
39 (CC_REGNUM 100) ; Condition code pseudo register
40 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
41 ]
42 )
43 ;; 3rd operand to select_dominance_cc_mode
44 (define_constants
45 [(DOM_CC_X_AND_Y 0)
46 (DOM_CC_NX_OR_Y 1)
47 (DOM_CC_X_OR_Y 2)
48 ]
49 )
50 ;; conditional compare combination
51 (define_constants
52 [(CMP_CMP 0)
53 (CMN_CMP 1)
54 (CMP_CMN 2)
55 (CMN_CMN 3)
56 (NUM_OF_COND_CMP 4)
57 ]
58 )
59
60 \f
61 ;;---------------------------------------------------------------------------
62 ;; Attributes
63
64 ;; Processor type. This is created automatically from arm-cores.def.
65 (include "arm-tune.md")
66
67 ;; Instruction classification types
68 (include "types.md")
69
70 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
71 ; generating ARM code. This is used to control the length of some insn
72 ; patterns that share the same RTL in both ARM and Thumb code.
73 (define_attr "is_thumb" "yes,no"
74 (const (if_then_else (symbol_ref "TARGET_THUMB")
75 (const_string "yes") (const_string "no"))))
76
77 ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
78 (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
79
80 ; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
81 (define_attr "is_thumb1" "yes,no"
82 (const (if_then_else (symbol_ref "TARGET_THUMB1")
83 (const_string "yes") (const_string "no"))))
84
85 ; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
86 ; The arm_restrict_it flag enables the "short IT" feature which
87 ; restricts IT blocks to a single 16-bit instruction.
88 ; This attribute should only be used on 16-bit Thumb-2 instructions
89 ; which may be predicated (the "predicable" attribute must be set).
90 (define_attr "predicable_short_it" "no,yes" (const_string "no"))
91
92 ; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
93 ; This attribute should only be used on instructions which may emit
94 ; an IT block in their expansion which is not a short IT.
95 (define_attr "enabled_for_short_it" "no,yes" (const_string "yes"))
96
97 ;; Operand number of an input operand that is shifted. Zero if the
98 ;; given instruction does not shift one of its input operands.
99 (define_attr "shift" "" (const_int 0))
100
101 ;; [For compatibility with AArch64 in pipeline models]
102 ;; Attribute that specifies whether or not the instruction touches fp
103 ;; registers.
104 (define_attr "fp" "no,yes" (const_string "no"))
105
106 ; Floating Point Unit. If we only have floating point emulation, then there
107 ; is no point in scheduling the floating point insns. (Well, for best
108 ; performance we should try and group them together).
109 (define_attr "fpu" "none,vfp"
110 (const (symbol_ref "arm_fpu_attr")))
111
112 ; Predicated means that the insn form is conditionally executed based on a
113 ; predicate. We default to 'no' because no Thumb patterns match this rule
114 ; and not all ARM insns do.
115 (define_attr "predicated" "yes,no" (const_string "no"))
116
117 ; LENGTH of an instruction (in bytes)
118 (define_attr "length" ""
119 (const_int 4))
120
121 ; The architecture which supports the instruction (or alternative).
122 ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
123 ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
124 ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
125 ; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
126 ; Baseline. This attribute is used to compute attribute "enabled",
127 ; use type "any" to enable an alternative in all cases.
128 (define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
129 (const_string "any"))
130
131 (define_attr "arch_enabled" "no,yes"
132 (cond [(eq_attr "arch" "any")
133 (const_string "yes")
134
135 (and (eq_attr "arch" "a")
136 (match_test "TARGET_ARM"))
137 (const_string "yes")
138
139 (and (eq_attr "arch" "t")
140 (match_test "TARGET_THUMB"))
141 (const_string "yes")
142
143 (and (eq_attr "arch" "t1")
144 (match_test "TARGET_THUMB1"))
145 (const_string "yes")
146
147 (and (eq_attr "arch" "t2")
148 (match_test "TARGET_THUMB2"))
149 (const_string "yes")
150
151 (and (eq_attr "arch" "32")
152 (match_test "TARGET_32BIT"))
153 (const_string "yes")
154
155 (and (eq_attr "arch" "v6")
156 (match_test "TARGET_32BIT && arm_arch6"))
157 (const_string "yes")
158
159 (and (eq_attr "arch" "nov6")
160 (match_test "TARGET_32BIT && !arm_arch6"))
161 (const_string "yes")
162
163 (and (eq_attr "arch" "v6t2")
164 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
165 (const_string "yes")
166
167 (and (eq_attr "arch" "v8mb")
168 (match_test "TARGET_THUMB1 && arm_arch8"))
169 (const_string "yes")
170
171 (and (eq_attr "arch" "avoid_neon_for_64bits")
172 (match_test "TARGET_NEON")
173 (not (match_test "TARGET_PREFER_NEON_64BITS")))
174 (const_string "yes")
175
176 (and (eq_attr "arch" "neon_for_64bits")
177 (match_test "TARGET_NEON")
178 (match_test "TARGET_PREFER_NEON_64BITS"))
179 (const_string "yes")
180
181 (and (eq_attr "arch" "iwmmxt2")
182 (match_test "TARGET_REALLY_IWMMXT2"))
183 (const_string "yes")
184
185 (and (eq_attr "arch" "armv6_or_vfpv3")
186 (match_test "arm_arch6 || TARGET_VFP3"))
187 (const_string "yes")
188
189 (and (eq_attr "arch" "neon")
190 (match_test "TARGET_NEON"))
191 (const_string "yes")
192 ]
193
194 (const_string "no")))
195
196 (define_attr "opt" "any,speed,size"
197 (const_string "any"))
198
199 (define_attr "opt_enabled" "no,yes"
200 (cond [(eq_attr "opt" "any")
201 (const_string "yes")
202
203 (and (eq_attr "opt" "speed")
204 (match_test "optimize_function_for_speed_p (cfun)"))
205 (const_string "yes")
206
207 (and (eq_attr "opt" "size")
208 (match_test "optimize_function_for_size_p (cfun)"))
209 (const_string "yes")]
210 (const_string "no")))
211
212 (define_attr "use_literal_pool" "no,yes"
213 (cond [(and (eq_attr "type" "f_loads,f_loadd")
214 (match_test "CONSTANT_P (operands[1])"))
215 (const_string "yes")]
216 (const_string "no")))
217
218 ; Enable all alternatives that are both arch_enabled and insn_enabled.
219 ; FIXME:: opt_enabled has been temporarily removed till the time we have
220 ; an attribute that allows the use of such alternatives.
221 ; This depends on caching of speed_p, size_p on a per
222 ; alternative basis. The problem is that the enabled attribute
223 ; cannot depend on any state that is not cached or is not constant
224 ; for a compilation unit. We probably need a generic "hot/cold"
225 ; alternative which if implemented can help with this. We disable this
226 ; until such a time as this is implemented and / or the improvements or
227 ; regressions with removing this attribute are double checked.
228 ; See ashldi3_neon and <shift>di3_neon in neon.md.
229
230 (define_attr "enabled" "no,yes"
231 (cond [(and (eq_attr "predicable_short_it" "no")
232 (and (eq_attr "predicated" "yes")
233 (match_test "arm_restrict_it")))
234 (const_string "no")
235
236 (and (eq_attr "enabled_for_short_it" "no")
237 (match_test "arm_restrict_it"))
238 (const_string "no")
239
240 (eq_attr "arch_enabled" "no")
241 (const_string "no")]
242 (const_string "yes")))
243
244 ; POOL_RANGE is how far away from a constant pool entry that this insn
245 ; can be placed. If the distance is zero, then this insn will never
246 ; reference the pool.
247 ; Note that for Thumb constant pools the PC value is rounded down to the
248 ; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
249 ; Thumb insns) should be set to <max_range> - 2.
250 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
251 ; before its address. It is set to <max_range> - (8 + <data_size>).
252 (define_attr "arm_pool_range" "" (const_int 0))
253 (define_attr "thumb2_pool_range" "" (const_int 0))
254 (define_attr "arm_neg_pool_range" "" (const_int 0))
255 (define_attr "thumb2_neg_pool_range" "" (const_int 0))
256
257 (define_attr "pool_range" ""
258 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
259 (attr "arm_pool_range")))
260 (define_attr "neg_pool_range" ""
261 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
262 (attr "arm_neg_pool_range")))
263
264 ; An assembler sequence may clobber the condition codes without us knowing.
265 ; If such an insn references the pool, then we have no way of knowing how,
266 ; so use the most conservative value for pool_range.
267 (define_asm_attributes
268 [(set_attr "conds" "clob")
269 (set_attr "length" "4")
270 (set_attr "pool_range" "250")])
271
272 ; Load scheduling, set from the arm_ld_sched variable
273 ; initialized by arm_option_override()
274 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
275
276 ; condition codes: this one is used by final_prescan_insn to speed up
277 ; conditionalizing instructions. It saves having to scan the rtl to see if
278 ; it uses or alters the condition codes.
279 ;
280 ; USE means that the condition codes are used by the insn in the process of
281 ; outputting code, this means (at present) that we can't use the insn in
282 ; inlined branches
283 ;
284 ; SET means that the purpose of the insn is to set the condition codes in a
285 ; well defined manner.
286 ;
287 ; CLOB means that the condition codes are altered in an undefined manner, if
288 ; they are altered at all
289 ;
290 ; UNCONDITIONAL means the instruction cannot be conditionally executed and
291 ; that the instruction does not use or alter the condition codes.
292 ;
293 ; NOCOND means that the instruction does not use or alter the condition
294 ; codes but can be converted into a conditionally exectuted instruction.
295
296 (define_attr "conds" "use,set,clob,unconditional,nocond"
297 (if_then_else
298 (ior (eq_attr "is_thumb1" "yes")
299 (eq_attr "type" "call"))
300 (const_string "clob")
301 (if_then_else (eq_attr "is_neon_type" "no")
302 (const_string "nocond")
303 (const_string "unconditional"))))
304
305 ; Predicable means that the insn can be conditionally executed based on
306 ; an automatically added predicate (additional patterns are generated by
307 ; gen...). We default to 'no' because no Thumb patterns match this rule
308 ; and not all ARM patterns do.
309 (define_attr "predicable" "no,yes" (const_string "no"))
310
311 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
312 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
313 ; suffer blockages enough to warrant modelling this (and it can adversely
314 ; affect the schedule).
315 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
316
317 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
318 ; to stall the processor. Used with model_wbuf above.
319 (define_attr "write_conflict" "no,yes"
320 (if_then_else (eq_attr "type"
321 "block,call,load_4")
322 (const_string "yes")
323 (const_string "no")))
324
325 ; Classify the insns into those that take one cycle and those that take more
326 ; than one on the main cpu execution unit.
327 (define_attr "core_cycles" "single,multi"
328 (if_then_else (eq_attr "type"
329 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
330 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
331 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
332 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
333 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
334 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
335 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
336 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
337 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
338 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
339 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
340 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
341 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
342 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
343 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
344 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
345 (const_string "single")
346 (const_string "multi")))
347
348 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
349 ;; distant label. Only applicable to Thumb code.
350 (define_attr "far_jump" "yes,no" (const_string "no"))
351
352
353 ;; The number of machine instructions this pattern expands to.
354 ;; Used for Thumb-2 conditional execution.
355 (define_attr "ce_count" "" (const_int 1))
356
357 ;;---------------------------------------------------------------------------
358 ;; Unspecs
359
360 (include "unspecs.md")
361
362 ;;---------------------------------------------------------------------------
363 ;; Mode iterators
364
365 (include "iterators.md")
366
367 ;;---------------------------------------------------------------------------
368 ;; Predicates
369
370 (include "predicates.md")
371 (include "constraints.md")
372
373 ;;---------------------------------------------------------------------------
374 ;; Pipeline descriptions
375
376 (define_attr "tune_cortexr4" "yes,no"
377 (const (if_then_else
378 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
379 (const_string "yes")
380 (const_string "no"))))
381
382 ;; True if the generic scheduling description should be used.
383
384 (define_attr "generic_sched" "yes,no"
385 (const (if_then_else
386 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
387 arm926ejs,arm10e,arm1026ejs,arm1136js,\
388 arm1136jfs,cortexa5,cortexa7,cortexa8,\
389 cortexa9,cortexa12,cortexa15,cortexa17,\
390 cortexa53,cortexa57,cortexm4,cortexm7,\
391 exynosm1,marvell_pj4,xgene1")
392 (eq_attr "tune_cortexr4" "yes"))
393 (const_string "no")
394 (const_string "yes"))))
395
396 (define_attr "generic_vfp" "yes,no"
397 (const (if_then_else
398 (and (eq_attr "fpu" "vfp")
399 (eq_attr "tune" "!arm10e,cortexa5,cortexa7,\
400 cortexa8,cortexa9,cortexa53,cortexm4,\
401 cortexm7,marvell_pj4,xgene1")
402 (eq_attr "tune_cortexr4" "no"))
403 (const_string "yes")
404 (const_string "no"))))
405
406 (include "marvell-f-iwmmxt.md")
407 (include "arm-generic.md")
408 (include "arm926ejs.md")
409 (include "arm1020e.md")
410 (include "arm1026ejs.md")
411 (include "arm1136jfs.md")
412 (include "fa526.md")
413 (include "fa606te.md")
414 (include "fa626te.md")
415 (include "fmp626.md")
416 (include "fa726te.md")
417 (include "cortex-a5.md")
418 (include "cortex-a7.md")
419 (include "cortex-a8.md")
420 (include "cortex-a9.md")
421 (include "cortex-a15.md")
422 (include "cortex-a17.md")
423 (include "cortex-a53.md")
424 (include "cortex-a57.md")
425 (include "cortex-r4.md")
426 (include "cortex-r4f.md")
427 (include "cortex-m7.md")
428 (include "cortex-m4.md")
429 (include "cortex-m4-fpu.md")
430 (include "exynos-m1.md")
431 (include "vfp11.md")
432 (include "marvell-pj4.md")
433 (include "xgene1.md")
434
435 \f
436 ;;---------------------------------------------------------------------------
437 ;; Insn patterns
438 ;;
439 ;; Addition insns.
440
441 ;; Note: For DImode insns, there is normally no reason why operands should
442 ;; not be in the same register, what we don't want is for something being
443 ;; written to partially overlap something that is an input.
444
445 (define_expand "adddi3"
446 [(parallel
447 [(set (match_operand:DI 0 "s_register_operand" "")
448 (plus:DI (match_operand:DI 1 "s_register_operand" "")
449 (match_operand:DI 2 "arm_adddi_operand" "")))
450 (clobber (reg:CC CC_REGNUM))])]
451 "TARGET_EITHER"
452 "
453 if (TARGET_THUMB1)
454 {
455 if (!REG_P (operands[1]))
456 operands[1] = force_reg (DImode, operands[1]);
457 if (!REG_P (operands[2]))
458 operands[2] = force_reg (DImode, operands[2]);
459 }
460 "
461 )
462
463 (define_insn_and_split "*arm_adddi3"
464 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r,&r,&r")
465 (plus:DI (match_operand:DI 1 "arm_general_register_operand" "%0, 0, r, 0, r")
466 (match_operand:DI 2 "arm_general_adddi_operand" "r, 0, r, Dd, Dd")))
467 (clobber (reg:CC CC_REGNUM))]
468 "TARGET_32BIT && !TARGET_NEON"
469 "#"
470 "TARGET_32BIT && ((!TARGET_NEON && !TARGET_IWMMXT) || reload_completed)"
471 [(parallel [(set (reg:CC_C CC_REGNUM)
472 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
473 (match_dup 1)))
474 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
475 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
476 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
477 "
478 {
479 operands[3] = gen_highpart (SImode, operands[0]);
480 operands[0] = gen_lowpart (SImode, operands[0]);
481 operands[4] = gen_highpart (SImode, operands[1]);
482 operands[1] = gen_lowpart (SImode, operands[1]);
483 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
484 operands[2] = gen_lowpart (SImode, operands[2]);
485 }"
486 [(set_attr "conds" "clob")
487 (set_attr "length" "8")
488 (set_attr "type" "multiple")]
489 )
490
491 (define_insn_and_split "*adddi_sesidi_di"
492 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
493 (plus:DI (sign_extend:DI
494 (match_operand:SI 2 "s_register_operand" "r,r"))
495 (match_operand:DI 1 "s_register_operand" "0,r")))
496 (clobber (reg:CC CC_REGNUM))]
497 "TARGET_32BIT"
498 "#"
499 "TARGET_32BIT && reload_completed"
500 [(parallel [(set (reg:CC_C CC_REGNUM)
501 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
502 (match_dup 1)))
503 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
504 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
505 (const_int 31))
506 (match_dup 4))
507 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
508 "
509 {
510 operands[3] = gen_highpart (SImode, operands[0]);
511 operands[0] = gen_lowpart (SImode, operands[0]);
512 operands[4] = gen_highpart (SImode, operands[1]);
513 operands[1] = gen_lowpart (SImode, operands[1]);
514 operands[2] = gen_lowpart (SImode, operands[2]);
515 }"
516 [(set_attr "conds" "clob")
517 (set_attr "length" "8")
518 (set_attr "type" "multiple")]
519 )
520
521 (define_insn_and_split "*adddi_zesidi_di"
522 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
523 (plus:DI (zero_extend:DI
524 (match_operand:SI 2 "s_register_operand" "r,r"))
525 (match_operand:DI 1 "s_register_operand" "0,r")))
526 (clobber (reg:CC CC_REGNUM))]
527 "TARGET_32BIT"
528 "#"
529 "TARGET_32BIT && reload_completed"
530 [(parallel [(set (reg:CC_C CC_REGNUM)
531 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
532 (match_dup 1)))
533 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
534 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
535 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
536 "
537 {
538 operands[3] = gen_highpart (SImode, operands[0]);
539 operands[0] = gen_lowpart (SImode, operands[0]);
540 operands[4] = gen_highpart (SImode, operands[1]);
541 operands[1] = gen_lowpart (SImode, operands[1]);
542 operands[2] = gen_lowpart (SImode, operands[2]);
543 }"
544 [(set_attr "conds" "clob")
545 (set_attr "length" "8")
546 (set_attr "type" "multiple")]
547 )
548
549 (define_expand "addv<mode>4"
550 [(match_operand:SIDI 0 "register_operand")
551 (match_operand:SIDI 1 "register_operand")
552 (match_operand:SIDI 2 "register_operand")
553 (match_operand 3 "")]
554 "TARGET_32BIT"
555 {
556 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
557 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
558
559 DONE;
560 })
561
562 (define_expand "uaddv<mode>4"
563 [(match_operand:SIDI 0 "register_operand")
564 (match_operand:SIDI 1 "register_operand")
565 (match_operand:SIDI 2 "register_operand")
566 (match_operand 3 "")]
567 "TARGET_32BIT"
568 {
569 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
570 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
571
572 DONE;
573 })
574
575 (define_expand "addsi3"
576 [(set (match_operand:SI 0 "s_register_operand" "")
577 (plus:SI (match_operand:SI 1 "s_register_operand" "")
578 (match_operand:SI 2 "reg_or_int_operand" "")))]
579 "TARGET_EITHER"
580 "
581 if (TARGET_32BIT && CONST_INT_P (operands[2]))
582 {
583 arm_split_constant (PLUS, SImode, NULL_RTX,
584 INTVAL (operands[2]), operands[0], operands[1],
585 optimize && can_create_pseudo_p ());
586 DONE;
587 }
588 "
589 )
590
591 ; If there is a scratch available, this will be faster than synthesizing the
592 ; addition.
593 (define_peephole2
594 [(match_scratch:SI 3 "r")
595 (set (match_operand:SI 0 "arm_general_register_operand" "")
596 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
597 (match_operand:SI 2 "const_int_operand" "")))]
598 "TARGET_32BIT &&
599 !(const_ok_for_arm (INTVAL (operands[2]))
600 || const_ok_for_arm (-INTVAL (operands[2])))
601 && const_ok_for_arm (~INTVAL (operands[2]))"
602 [(set (match_dup 3) (match_dup 2))
603 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
604 ""
605 )
606
607 ;; The r/r/k alternative is required when reloading the address
608 ;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
609 ;; put the duplicated register first, and not try the commutative version.
610 (define_insn_and_split "*arm_addsi3"
611 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
612 (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,r ,rk,k ,rk,k,r,rk,k ,rk")
613 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
614 "TARGET_32BIT"
615 "@
616 add%?\\t%0, %0, %2
617 add%?\\t%0, %1, %2
618 add%?\\t%0, %1, %2
619 add%?\\t%0, %1, %2
620 add%?\\t%0, %1, %2
621 add%?\\t%0, %1, %2
622 add%?\\t%0, %2, %1
623 add%?\\t%0, %1, %2
624 addw%?\\t%0, %1, %2
625 addw%?\\t%0, %1, %2
626 sub%?\\t%0, %1, #%n2
627 sub%?\\t%0, %1, #%n2
628 sub%?\\t%0, %1, #%n2
629 subw%?\\t%0, %1, #%n2
630 subw%?\\t%0, %1, #%n2
631 #"
632 "TARGET_32BIT
633 && CONST_INT_P (operands[2])
634 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
635 && (reload_completed || !arm_eliminable_register (operands[1]))"
636 [(clobber (const_int 0))]
637 "
638 arm_split_constant (PLUS, SImode, curr_insn,
639 INTVAL (operands[2]), operands[0],
640 operands[1], 0);
641 DONE;
642 "
643 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
644 (set_attr "predicable" "yes")
645 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
646 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
647 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
648 (const_string "alu_imm")
649 (const_string "alu_sreg")))
650 ]
651 )
652
653 (define_insn_and_split "adddi3_compareV"
654 [(set (reg:CC_V CC_REGNUM)
655 (ne:CC_V
656 (plus:TI
657 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
658 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
659 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
660 (set (match_operand:DI 0 "register_operand" "=&r")
661 (plus:DI (match_dup 1) (match_dup 2)))]
662 "TARGET_32BIT"
663 "#"
664 "&& reload_completed"
665 [(parallel [(set (reg:CC_C CC_REGNUM)
666 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
667 (match_dup 1)))
668 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
669 (parallel [(set (reg:CC_V CC_REGNUM)
670 (ne:CC_V
671 (plus:DI (plus:DI
672 (sign_extend:DI (match_dup 4))
673 (sign_extend:DI (match_dup 5)))
674 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
675 (plus:DI (sign_extend:DI
676 (plus:SI (match_dup 4) (match_dup 5)))
677 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
678 (set (match_dup 3) (plus:SI (plus:SI
679 (match_dup 4) (match_dup 5))
680 (ltu:SI (reg:CC_C CC_REGNUM)
681 (const_int 0))))])]
682 "
683 {
684 operands[3] = gen_highpart (SImode, operands[0]);
685 operands[0] = gen_lowpart (SImode, operands[0]);
686 operands[4] = gen_highpart (SImode, operands[1]);
687 operands[1] = gen_lowpart (SImode, operands[1]);
688 operands[5] = gen_highpart (SImode, operands[2]);
689 operands[2] = gen_lowpart (SImode, operands[2]);
690 }"
691 [(set_attr "conds" "set")
692 (set_attr "length" "8")
693 (set_attr "type" "multiple")]
694 )
695
696 (define_insn "addsi3_compareV"
697 [(set (reg:CC_V CC_REGNUM)
698 (ne:CC_V
699 (plus:DI
700 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
701 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
702 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
703 (set (match_operand:SI 0 "register_operand" "=r")
704 (plus:SI (match_dup 1) (match_dup 2)))]
705 "TARGET_32BIT"
706 "adds%?\\t%0, %1, %2"
707 [(set_attr "conds" "set")
708 (set_attr "type" "alus_sreg")]
709 )
710
711 (define_insn "*addsi3_compareV_upper"
712 [(set (reg:CC_V CC_REGNUM)
713 (ne:CC_V
714 (plus:DI
715 (plus:DI
716 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
717 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
718 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
719 (plus:DI (sign_extend:DI
720 (plus:SI (match_dup 1) (match_dup 2)))
721 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
722 (set (match_operand:SI 0 "register_operand" "=r")
723 (plus:SI
724 (plus:SI (match_dup 1) (match_dup 2))
725 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
726 "TARGET_32BIT"
727 "adcs%?\\t%0, %1, %2"
728 [(set_attr "conds" "set")
729 (set_attr "type" "adcs_reg")]
730 )
731
732 (define_insn_and_split "adddi3_compareC"
733 [(set (reg:CC_C CC_REGNUM)
734 (ne:CC_C
735 (plus:TI
736 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
737 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
738 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
739 (set (match_operand:DI 0 "register_operand" "=&r")
740 (plus:DI (match_dup 1) (match_dup 2)))]
741 "TARGET_32BIT"
742 "#"
743 "&& reload_completed"
744 [(parallel [(set (reg:CC_C CC_REGNUM)
745 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
746 (match_dup 1)))
747 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
748 (parallel [(set (reg:CC_C CC_REGNUM)
749 (ne:CC_C
750 (plus:DI (plus:DI
751 (zero_extend:DI (match_dup 4))
752 (zero_extend:DI (match_dup 5)))
753 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
754 (plus:DI (zero_extend:DI
755 (plus:SI (match_dup 4) (match_dup 5)))
756 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
757 (set (match_dup 3) (plus:SI
758 (plus:SI (match_dup 4) (match_dup 5))
759 (ltu:SI (reg:CC_C CC_REGNUM)
760 (const_int 0))))])]
761 "
762 {
763 operands[3] = gen_highpart (SImode, operands[0]);
764 operands[0] = gen_lowpart (SImode, operands[0]);
765 operands[4] = gen_highpart (SImode, operands[1]);
766 operands[5] = gen_highpart (SImode, operands[2]);
767 operands[1] = gen_lowpart (SImode, operands[1]);
768 operands[2] = gen_lowpart (SImode, operands[2]);
769 }"
770 [(set_attr "conds" "set")
771 (set_attr "length" "8")
772 (set_attr "type" "multiple")]
773 )
774
775 (define_insn "*addsi3_compareC_upper"
776 [(set (reg:CC_C CC_REGNUM)
777 (ne:CC_C
778 (plus:DI
779 (plus:DI
780 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
781 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
782 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
783 (plus:DI (zero_extend:DI
784 (plus:SI (match_dup 1) (match_dup 2)))
785 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
786 (set (match_operand:SI 0 "register_operand" "=r")
787 (plus:SI
788 (plus:SI (match_dup 1) (match_dup 2))
789 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
790 "TARGET_32BIT"
791 "adcs%?\\t%0, %1, %2"
792 [(set_attr "conds" "set")
793 (set_attr "type" "adcs_reg")]
794 )
795
796 (define_insn "addsi3_compareC"
797 [(set (reg:CC_C CC_REGNUM)
798 (ne:CC_C
799 (plus:DI
800 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
801 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
802 (zero_extend:DI
803 (plus:SI (match_dup 1) (match_dup 2)))))
804 (set (match_operand:SI 0 "register_operand" "=r")
805 (plus:SI (match_dup 1) (match_dup 2)))]
806 "TARGET_32BIT"
807 "adds%?\\t%0, %1, %2"
808 [(set_attr "conds" "set")
809 (set_attr "type" "alus_sreg")]
810 )
811
812 (define_insn "addsi3_compare0"
813 [(set (reg:CC_NOOV CC_REGNUM)
814 (compare:CC_NOOV
815 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
816 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
817 (const_int 0)))
818 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
819 (plus:SI (match_dup 1) (match_dup 2)))]
820 "TARGET_ARM"
821 "@
822 adds%?\\t%0, %1, %2
823 subs%?\\t%0, %1, #%n2
824 adds%?\\t%0, %1, %2"
825 [(set_attr "conds" "set")
826 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
827 )
828
829 (define_insn "*addsi3_compare0_scratch"
830 [(set (reg:CC_NOOV CC_REGNUM)
831 (compare:CC_NOOV
832 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
833 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
834 (const_int 0)))]
835 "TARGET_ARM"
836 "@
837 cmn%?\\t%0, %1
838 cmp%?\\t%0, #%n1
839 cmn%?\\t%0, %1"
840 [(set_attr "conds" "set")
841 (set_attr "predicable" "yes")
842 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
843 )
844
845 (define_insn "*compare_negsi_si"
846 [(set (reg:CC_Z CC_REGNUM)
847 (compare:CC_Z
848 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
849 (match_operand:SI 1 "s_register_operand" "l,r")))]
850 "TARGET_32BIT"
851 "cmn%?\\t%1, %0"
852 [(set_attr "conds" "set")
853 (set_attr "predicable" "yes")
854 (set_attr "arch" "t2,*")
855 (set_attr "length" "2,4")
856 (set_attr "predicable_short_it" "yes,no")
857 (set_attr "type" "alus_sreg")]
858 )
859
860 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
861 ;; addend is a constant.
862 (define_insn "cmpsi2_addneg"
863 [(set (reg:CC CC_REGNUM)
864 (compare:CC
865 (match_operand:SI 1 "s_register_operand" "r,r")
866 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
867 (set (match_operand:SI 0 "s_register_operand" "=r,r")
868 (plus:SI (match_dup 1)
869 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
870 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
871 "@
872 adds%?\\t%0, %1, %3
873 subs%?\\t%0, %1, #%n3"
874 [(set_attr "conds" "set")
875 (set_attr "type" "alus_sreg")]
876 )
877
878 ;; Convert the sequence
879 ;; sub rd, rn, #1
880 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
881 ;; bne dest
882 ;; into
883 ;; subs rd, rn, #1
884 ;; bcs dest ((unsigned)rn >= 1)
885 ;; similarly for the beq variant using bcc.
886 ;; This is a common looping idiom (while (n--))
887 (define_peephole2
888 [(set (match_operand:SI 0 "arm_general_register_operand" "")
889 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
890 (const_int -1)))
891 (set (match_operand 2 "cc_register" "")
892 (compare (match_dup 0) (const_int -1)))
893 (set (pc)
894 (if_then_else (match_operator 3 "equality_operator"
895 [(match_dup 2) (const_int 0)])
896 (match_operand 4 "" "")
897 (match_operand 5 "" "")))]
898 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
899 [(parallel[
900 (set (match_dup 2)
901 (compare:CC
902 (match_dup 1) (const_int 1)))
903 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
904 (set (pc)
905 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
906 (match_dup 4)
907 (match_dup 5)))]
908 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
909 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
910 ? GEU : LTU),
911 VOIDmode,
912 operands[2], const0_rtx);"
913 )
914
915 ;; The next four insns work because they compare the result with one of
916 ;; the operands, and we know that the use of the condition code is
917 ;; either GEU or LTU, so we can use the carry flag from the addition
918 ;; instead of doing the compare a second time.
919 (define_insn "*addsi3_compare_op1"
920 [(set (reg:CC_C CC_REGNUM)
921 (compare:CC_C
922 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
923 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
924 (match_dup 1)))
925 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
926 (plus:SI (match_dup 1) (match_dup 2)))]
927 "TARGET_32BIT"
928 "@
929 adds%?\\t%0, %1, %2
930 subs%?\\t%0, %1, #%n2
931 adds%?\\t%0, %1, %2"
932 [(set_attr "conds" "set")
933 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
934 )
935
936 (define_insn "*addsi3_compare_op2"
937 [(set (reg:CC_C CC_REGNUM)
938 (compare:CC_C
939 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
940 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
941 (match_dup 2)))
942 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
943 (plus:SI (match_dup 1) (match_dup 2)))]
944 "TARGET_32BIT"
945 "@
946 adds%?\\t%0, %1, %2
947 subs%?\\t%0, %1, #%n2
948 adds%?\\t%0, %1, %2"
949 [(set_attr "conds" "set")
950 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
951 )
952
953 (define_insn "*compare_addsi2_op0"
954 [(set (reg:CC_C CC_REGNUM)
955 (compare:CC_C
956 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
957 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
958 (match_dup 0)))]
959 "TARGET_32BIT"
960 "@
961 cmp%?\\t%0, #%n1
962 cmn%?\\t%0, %1
963 cmn%?\\t%0, %1
964 cmp%?\\t%0, #%n1
965 cmn%?\\t%0, %1"
966 [(set_attr "conds" "set")
967 (set_attr "predicable" "yes")
968 (set_attr "arch" "t2,t2,*,*,*")
969 (set_attr "predicable_short_it" "yes,yes,no,no,no")
970 (set_attr "length" "2,2,4,4,4")
971 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
972 )
973
974 (define_insn "*compare_addsi2_op1"
975 [(set (reg:CC_C CC_REGNUM)
976 (compare:CC_C
977 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
978 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
979 (match_dup 1)))]
980 "TARGET_32BIT"
981 "@
982 cmp%?\\t%0, #%n1
983 cmn%?\\t%0, %1
984 cmn%?\\t%0, %1
985 cmp%?\\t%0, #%n1
986 cmn%?\\t%0, %1"
987 [(set_attr "conds" "set")
988 (set_attr "predicable" "yes")
989 (set_attr "arch" "t2,t2,*,*,*")
990 (set_attr "predicable_short_it" "yes,yes,no,no,no")
991 (set_attr "length" "2,2,4,4,4")
992 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
993 )
994
995 (define_insn "*addsi3_carryin_<optab>"
996 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
997 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
998 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
999 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1000 "TARGET_32BIT"
1001 "@
1002 adc%?\\t%0, %1, %2
1003 adc%?\\t%0, %1, %2
1004 sbc%?\\t%0, %1, #%B2"
1005 [(set_attr "conds" "use")
1006 (set_attr "predicable" "yes")
1007 (set_attr "arch" "t2,*,*")
1008 (set_attr "length" "4")
1009 (set_attr "predicable_short_it" "yes,no,no")
1010 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1011 )
1012
1013 (define_insn "*addsi3_carryin_alt2_<optab>"
1014 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1015 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1016 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1017 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
1018 "TARGET_32BIT"
1019 "@
1020 adc%?\\t%0, %1, %2
1021 adc%?\\t%0, %1, %2
1022 sbc%?\\t%0, %1, #%B2"
1023 [(set_attr "conds" "use")
1024 (set_attr "predicable" "yes")
1025 (set_attr "arch" "t2,*,*")
1026 (set_attr "length" "4")
1027 (set_attr "predicable_short_it" "yes,no,no")
1028 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1029 )
1030
1031 (define_insn "*addsi3_carryin_shift_<optab>"
1032 [(set (match_operand:SI 0 "s_register_operand" "=r")
1033 (plus:SI (plus:SI
1034 (match_operator:SI 2 "shift_operator"
1035 [(match_operand:SI 3 "s_register_operand" "r")
1036 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1037 (match_operand:SI 1 "s_register_operand" "r"))
1038 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1039 "TARGET_32BIT"
1040 "adc%?\\t%0, %1, %3%S2"
1041 [(set_attr "conds" "use")
1042 (set_attr "predicable" "yes")
1043 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1044 (const_string "alu_shift_imm")
1045 (const_string "alu_shift_reg")))]
1046 )
1047
1048 (define_insn "*addsi3_carryin_clobercc_<optab>"
1049 [(set (match_operand:SI 0 "s_register_operand" "=r")
1050 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1051 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1052 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1053 (clobber (reg:CC CC_REGNUM))]
1054 "TARGET_32BIT"
1055 "adcs%?\\t%0, %1, %2"
1056 [(set_attr "conds" "set")
1057 (set_attr "type" "adcs_reg")]
1058 )
1059
1060 (define_expand "subv<mode>4"
1061 [(match_operand:SIDI 0 "register_operand")
1062 (match_operand:SIDI 1 "register_operand")
1063 (match_operand:SIDI 2 "register_operand")
1064 (match_operand 3 "")]
1065 "TARGET_32BIT"
1066 {
1067 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1068 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1069
1070 DONE;
1071 })
1072
1073 (define_expand "usubv<mode>4"
1074 [(match_operand:SIDI 0 "register_operand")
1075 (match_operand:SIDI 1 "register_operand")
1076 (match_operand:SIDI 2 "register_operand")
1077 (match_operand 3 "")]
1078 "TARGET_32BIT"
1079 {
1080 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1081 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1082
1083 DONE;
1084 })
1085
1086 (define_insn_and_split "subdi3_compare1"
1087 [(set (reg:CC CC_REGNUM)
1088 (compare:CC
1089 (match_operand:DI 1 "register_operand" "r")
1090 (match_operand:DI 2 "register_operand" "r")))
1091 (set (match_operand:DI 0 "register_operand" "=&r")
1092 (minus:DI (match_dup 1) (match_dup 2)))]
1093 "TARGET_32BIT"
1094 "#"
1095 "&& reload_completed"
1096 [(parallel [(set (reg:CC CC_REGNUM)
1097 (compare:CC (match_dup 1) (match_dup 2)))
1098 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1099 (parallel [(set (reg:CC CC_REGNUM)
1100 (compare:CC (match_dup 4) (match_dup 5)))
1101 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1102 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
1103 {
1104 operands[3] = gen_highpart (SImode, operands[0]);
1105 operands[0] = gen_lowpart (SImode, operands[0]);
1106 operands[4] = gen_highpart (SImode, operands[1]);
1107 operands[1] = gen_lowpart (SImode, operands[1]);
1108 operands[5] = gen_highpart (SImode, operands[2]);
1109 operands[2] = gen_lowpart (SImode, operands[2]);
1110 }
1111 [(set_attr "conds" "set")
1112 (set_attr "length" "8")
1113 (set_attr "type" "multiple")]
1114 )
1115
1116 (define_insn "subsi3_compare1"
1117 [(set (reg:CC CC_REGNUM)
1118 (compare:CC
1119 (match_operand:SI 1 "register_operand" "r")
1120 (match_operand:SI 2 "register_operand" "r")))
1121 (set (match_operand:SI 0 "register_operand" "=r")
1122 (minus:SI (match_dup 1) (match_dup 2)))]
1123 "TARGET_32BIT"
1124 "subs%?\\t%0, %1, %2"
1125 [(set_attr "conds" "set")
1126 (set_attr "type" "alus_sreg")]
1127 )
1128
1129 (define_insn "*subsi3_carryin"
1130 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1131 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1132 (match_operand:SI 2 "s_register_operand" "r,r,r"))
1133 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1134 "TARGET_32BIT"
1135 "@
1136 sbc%?\\t%0, %1, %2
1137 rsc%?\\t%0, %2, %1
1138 sbc%?\\t%0, %2, %2, lsl #1"
1139 [(set_attr "conds" "use")
1140 (set_attr "arch" "*,a,t2")
1141 (set_attr "predicable" "yes")
1142 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
1143 )
1144
1145 (define_insn "*subsi3_carryin_const"
1146 [(set (match_operand:SI 0 "s_register_operand" "=r")
1147 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1148 (match_operand:SI 2 "arm_neg_immediate_operand" "L"))
1149 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1150 "TARGET_32BIT"
1151 "sbc\\t%0, %1, #%n2"
1152 [(set_attr "conds" "use")
1153 (set_attr "type" "adc_imm")]
1154 )
1155
1156 (define_insn "*subsi3_carryin_const0"
1157 [(set (match_operand:SI 0 "s_register_operand" "=r")
1158 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
1159 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1160 "TARGET_32BIT"
1161 "sbc\\t%0, %1, #0"
1162 [(set_attr "conds" "use")
1163 (set_attr "type" "adc_imm")]
1164 )
1165
1166 (define_insn "*subsi3_carryin_compare"
1167 [(set (reg:CC CC_REGNUM)
1168 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1169 (match_operand:SI 2 "s_register_operand" "r")))
1170 (set (match_operand:SI 0 "s_register_operand" "=r")
1171 (minus:SI (minus:SI (match_dup 1)
1172 (match_dup 2))
1173 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1174 "TARGET_32BIT"
1175 "sbcs\\t%0, %1, %2"
1176 [(set_attr "conds" "set")
1177 (set_attr "type" "adcs_reg")]
1178 )
1179
1180 (define_insn "*subsi3_carryin_compare_const"
1181 [(set (reg:CC CC_REGNUM)
1182 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1183 (match_operand:SI 2 "const_int_I_operand" "I")))
1184 (set (match_operand:SI 0 "s_register_operand" "=r")
1185 (minus:SI (plus:SI (match_dup 1)
1186 (match_operand:SI 3 "arm_neg_immediate_operand" "L"))
1187 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1188 "TARGET_32BIT
1189 && (INTVAL (operands[2])
1190 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
1191 "sbcs\\t%0, %1, #%n3"
1192 [(set_attr "conds" "set")
1193 (set_attr "type" "adcs_imm")]
1194 )
1195
1196 (define_insn "*subsi3_carryin_compare_const0"
1197 [(set (reg:CC CC_REGNUM)
1198 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1199 (const_int 0)))
1200 (set (match_operand:SI 0 "s_register_operand" "=r")
1201 (minus:SI (match_dup 1)
1202 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1203 "TARGET_32BIT"
1204 "sbcs\\t%0, %1, #0"
1205 [(set_attr "conds" "set")
1206 (set_attr "type" "adcs_imm")]
1207 )
1208
1209 (define_insn "*subsi3_carryin_shift"
1210 [(set (match_operand:SI 0 "s_register_operand" "=r")
1211 (minus:SI (minus:SI
1212 (match_operand:SI 1 "s_register_operand" "r")
1213 (match_operator:SI 2 "shift_operator"
1214 [(match_operand:SI 3 "s_register_operand" "r")
1215 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1216 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1217 "TARGET_32BIT"
1218 "sbc%?\\t%0, %1, %3%S2"
1219 [(set_attr "conds" "use")
1220 (set_attr "predicable" "yes")
1221 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1222 (const_string "alu_shift_imm")
1223 (const_string "alu_shift_reg")))]
1224 )
1225
1226 (define_insn "*rsbsi3_carryin_shift"
1227 [(set (match_operand:SI 0 "s_register_operand" "=r")
1228 (minus:SI (minus:SI
1229 (match_operator:SI 2 "shift_operator"
1230 [(match_operand:SI 3 "s_register_operand" "r")
1231 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1232 (match_operand:SI 1 "s_register_operand" "r"))
1233 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1234 "TARGET_ARM"
1235 "rsc%?\\t%0, %1, %3%S2"
1236 [(set_attr "conds" "use")
1237 (set_attr "predicable" "yes")
1238 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1239 (const_string "alu_shift_imm")
1240 (const_string "alu_shift_reg")))]
1241 )
1242
1243 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1244 (define_split
1245 [(set (match_operand:SI 0 "s_register_operand" "")
1246 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1247 (match_operand:SI 2 "s_register_operand" ""))
1248 (const_int -1)))
1249 (clobber (match_operand:SI 3 "s_register_operand" ""))]
1250 "TARGET_32BIT"
1251 [(set (match_dup 3) (match_dup 1))
1252 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1253 "
1254 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1255 ")
1256
1257 (define_expand "addsf3"
1258 [(set (match_operand:SF 0 "s_register_operand" "")
1259 (plus:SF (match_operand:SF 1 "s_register_operand" "")
1260 (match_operand:SF 2 "s_register_operand" "")))]
1261 "TARGET_32BIT && TARGET_HARD_FLOAT"
1262 "
1263 ")
1264
1265 (define_expand "adddf3"
1266 [(set (match_operand:DF 0 "s_register_operand" "")
1267 (plus:DF (match_operand:DF 1 "s_register_operand" "")
1268 (match_operand:DF 2 "s_register_operand" "")))]
1269 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1270 "
1271 ")
1272
1273 (define_expand "subdi3"
1274 [(parallel
1275 [(set (match_operand:DI 0 "s_register_operand" "")
1276 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1277 (match_operand:DI 2 "s_register_operand" "")))
1278 (clobber (reg:CC CC_REGNUM))])]
1279 "TARGET_EITHER"
1280 "
1281 if (TARGET_THUMB1)
1282 {
1283 if (!REG_P (operands[1]))
1284 operands[1] = force_reg (DImode, operands[1]);
1285 if (!REG_P (operands[2]))
1286 operands[2] = force_reg (DImode, operands[2]);
1287 }
1288 "
1289 )
1290
1291 (define_insn_and_split "*arm_subdi3"
1292 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r")
1293 (minus:DI (match_operand:DI 1 "arm_general_register_operand" "0,r,0")
1294 (match_operand:DI 2 "arm_general_register_operand" "r,0,0")))
1295 (clobber (reg:CC CC_REGNUM))]
1296 "TARGET_32BIT && !TARGET_NEON"
1297 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1298 "&& (!TARGET_IWMMXT || reload_completed)"
1299 [(parallel [(set (reg:CC CC_REGNUM)
1300 (compare:CC (match_dup 1) (match_dup 2)))
1301 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1302 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1303 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1304 {
1305 operands[3] = gen_highpart (SImode, operands[0]);
1306 operands[0] = gen_lowpart (SImode, operands[0]);
1307 operands[4] = gen_highpart (SImode, operands[1]);
1308 operands[1] = gen_lowpart (SImode, operands[1]);
1309 operands[5] = gen_highpart (SImode, operands[2]);
1310 operands[2] = gen_lowpart (SImode, operands[2]);
1311 }
1312 [(set_attr "conds" "clob")
1313 (set_attr "length" "8")
1314 (set_attr "type" "multiple")]
1315 )
1316
1317 (define_insn_and_split "*subdi_di_zesidi"
1318 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1319 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1320 (zero_extend:DI
1321 (match_operand:SI 2 "s_register_operand" "r,r"))))
1322 (clobber (reg:CC CC_REGNUM))]
1323 "TARGET_32BIT"
1324 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1325 "&& reload_completed"
1326 [(parallel [(set (reg:CC CC_REGNUM)
1327 (compare:CC (match_dup 1) (match_dup 2)))
1328 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1329 (set (match_dup 3) (minus:SI (match_dup 4)
1330 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1331 {
1332 operands[3] = gen_highpart (SImode, operands[0]);
1333 operands[0] = gen_lowpart (SImode, operands[0]);
1334 operands[4] = gen_highpart (SImode, operands[1]);
1335 operands[1] = gen_lowpart (SImode, operands[1]);
1336 }
1337 [(set_attr "conds" "clob")
1338 (set_attr "length" "8")
1339 (set_attr "type" "multiple")]
1340 )
1341
1342 (define_insn_and_split "*subdi_di_sesidi"
1343 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1344 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1345 (sign_extend:DI
1346 (match_operand:SI 2 "s_register_operand" "r,r"))))
1347 (clobber (reg:CC CC_REGNUM))]
1348 "TARGET_32BIT"
1349 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1350 "&& reload_completed"
1351 [(parallel [(set (reg:CC CC_REGNUM)
1352 (compare:CC (match_dup 1) (match_dup 2)))
1353 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1354 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1355 (ashiftrt:SI (match_dup 2)
1356 (const_int 31)))
1357 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1358 {
1359 operands[3] = gen_highpart (SImode, operands[0]);
1360 operands[0] = gen_lowpart (SImode, operands[0]);
1361 operands[4] = gen_highpart (SImode, operands[1]);
1362 operands[1] = gen_lowpart (SImode, operands[1]);
1363 }
1364 [(set_attr "conds" "clob")
1365 (set_attr "length" "8")
1366 (set_attr "type" "multiple")]
1367 )
1368
1369 (define_insn_and_split "*subdi_zesidi_di"
1370 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1371 (minus:DI (zero_extend:DI
1372 (match_operand:SI 2 "s_register_operand" "r,r"))
1373 (match_operand:DI 1 "s_register_operand" "0,r")))
1374 (clobber (reg:CC CC_REGNUM))]
1375 "TARGET_ARM"
1376 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1377 ; is equivalent to:
1378 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1379 "&& reload_completed"
1380 [(parallel [(set (reg:CC CC_REGNUM)
1381 (compare:CC (match_dup 2) (match_dup 1)))
1382 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1383 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1384 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1385 {
1386 operands[3] = gen_highpart (SImode, operands[0]);
1387 operands[0] = gen_lowpart (SImode, operands[0]);
1388 operands[4] = gen_highpart (SImode, operands[1]);
1389 operands[1] = gen_lowpart (SImode, operands[1]);
1390 }
1391 [(set_attr "conds" "clob")
1392 (set_attr "length" "8")
1393 (set_attr "type" "multiple")]
1394 )
1395
1396 (define_insn_and_split "*subdi_sesidi_di"
1397 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1398 (minus:DI (sign_extend:DI
1399 (match_operand:SI 2 "s_register_operand" "r,r"))
1400 (match_operand:DI 1 "s_register_operand" "0,r")))
1401 (clobber (reg:CC CC_REGNUM))]
1402 "TARGET_ARM"
1403 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1404 ; is equivalent to:
1405 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1406 "&& reload_completed"
1407 [(parallel [(set (reg:CC CC_REGNUM)
1408 (compare:CC (match_dup 2) (match_dup 1)))
1409 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1410 (set (match_dup 3) (minus:SI (minus:SI
1411 (ashiftrt:SI (match_dup 2)
1412 (const_int 31))
1413 (match_dup 4))
1414 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1415 {
1416 operands[3] = gen_highpart (SImode, operands[0]);
1417 operands[0] = gen_lowpart (SImode, operands[0]);
1418 operands[4] = gen_highpart (SImode, operands[1]);
1419 operands[1] = gen_lowpart (SImode, operands[1]);
1420 }
1421 [(set_attr "conds" "clob")
1422 (set_attr "length" "8")
1423 (set_attr "type" "multiple")]
1424 )
1425
1426 (define_insn_and_split "*subdi_zesidi_zesidi"
1427 [(set (match_operand:DI 0 "s_register_operand" "=r")
1428 (minus:DI (zero_extend:DI
1429 (match_operand:SI 1 "s_register_operand" "r"))
1430 (zero_extend:DI
1431 (match_operand:SI 2 "s_register_operand" "r"))))
1432 (clobber (reg:CC CC_REGNUM))]
1433 "TARGET_32BIT"
1434 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1435 "&& reload_completed"
1436 [(parallel [(set (reg:CC CC_REGNUM)
1437 (compare:CC (match_dup 1) (match_dup 2)))
1438 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1439 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1440 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1441 {
1442 operands[3] = gen_highpart (SImode, operands[0]);
1443 operands[0] = gen_lowpart (SImode, operands[0]);
1444 }
1445 [(set_attr "conds" "clob")
1446 (set_attr "length" "8")
1447 (set_attr "type" "multiple")]
1448 )
1449
1450 (define_expand "subsi3"
1451 [(set (match_operand:SI 0 "s_register_operand" "")
1452 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1453 (match_operand:SI 2 "s_register_operand" "")))]
1454 "TARGET_EITHER"
1455 "
1456 if (CONST_INT_P (operands[1]))
1457 {
1458 if (TARGET_32BIT)
1459 {
1460 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1461 operands[1] = force_reg (SImode, operands[1]);
1462 else
1463 {
1464 arm_split_constant (MINUS, SImode, NULL_RTX,
1465 INTVAL (operands[1]), operands[0],
1466 operands[2],
1467 optimize && can_create_pseudo_p ());
1468 DONE;
1469 }
1470 }
1471 else /* TARGET_THUMB1 */
1472 operands[1] = force_reg (SImode, operands[1]);
1473 }
1474 "
1475 )
1476
1477 ; ??? Check Thumb-2 split length
1478 (define_insn_and_split "*arm_subsi3_insn"
1479 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1480 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1481 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
1482 "TARGET_32BIT"
1483 "@
1484 sub%?\\t%0, %1, %2
1485 sub%?\\t%0, %2
1486 sub%?\\t%0, %1, %2
1487 rsb%?\\t%0, %2, %1
1488 rsb%?\\t%0, %2, %1
1489 sub%?\\t%0, %1, %2
1490 sub%?\\t%0, %1, %2
1491 sub%?\\t%0, %1, %2
1492 #"
1493 "&& (CONST_INT_P (operands[1])
1494 && !const_ok_for_arm (INTVAL (operands[1])))"
1495 [(clobber (const_int 0))]
1496 "
1497 arm_split_constant (MINUS, SImode, curr_insn,
1498 INTVAL (operands[1]), operands[0], operands[2], 0);
1499 DONE;
1500 "
1501 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1502 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
1503 (set_attr "predicable" "yes")
1504 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
1505 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
1506 )
1507
1508 (define_peephole2
1509 [(match_scratch:SI 3 "r")
1510 (set (match_operand:SI 0 "arm_general_register_operand" "")
1511 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1512 (match_operand:SI 2 "arm_general_register_operand" "")))]
1513 "TARGET_32BIT
1514 && !const_ok_for_arm (INTVAL (operands[1]))
1515 && const_ok_for_arm (~INTVAL (operands[1]))"
1516 [(set (match_dup 3) (match_dup 1))
1517 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1518 ""
1519 )
1520
1521 (define_insn "subsi3_compare0"
1522 [(set (reg:CC_NOOV CC_REGNUM)
1523 (compare:CC_NOOV
1524 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1525 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
1526 (const_int 0)))
1527 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1528 (minus:SI (match_dup 1) (match_dup 2)))]
1529 "TARGET_32BIT"
1530 "@
1531 subs%?\\t%0, %1, %2
1532 subs%?\\t%0, %1, %2
1533 rsbs%?\\t%0, %2, %1"
1534 [(set_attr "conds" "set")
1535 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1536 )
1537
1538 (define_insn "subsi3_compare"
1539 [(set (reg:CC CC_REGNUM)
1540 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1541 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1542 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1543 (minus:SI (match_dup 1) (match_dup 2)))]
1544 "TARGET_32BIT"
1545 "@
1546 subs%?\\t%0, %1, %2
1547 subs%?\\t%0, %1, %2
1548 rsbs%?\\t%0, %2, %1"
1549 [(set_attr "conds" "set")
1550 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1551 )
1552
1553 (define_expand "subsf3"
1554 [(set (match_operand:SF 0 "s_register_operand" "")
1555 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1556 (match_operand:SF 2 "s_register_operand" "")))]
1557 "TARGET_32BIT && TARGET_HARD_FLOAT"
1558 "
1559 ")
1560
1561 (define_expand "subdf3"
1562 [(set (match_operand:DF 0 "s_register_operand" "")
1563 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1564 (match_operand:DF 2 "s_register_operand" "")))]
1565 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1566 "
1567 ")
1568
1569 \f
1570 ;; Multiplication insns
1571
1572 (define_expand "mulhi3"
1573 [(set (match_operand:HI 0 "s_register_operand" "")
1574 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1575 (match_operand:HI 2 "s_register_operand" "")))]
1576 "TARGET_DSP_MULTIPLY"
1577 "
1578 {
1579 rtx result = gen_reg_rtx (SImode);
1580 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1581 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1582 DONE;
1583 }"
1584 )
1585
1586 (define_expand "mulsi3"
1587 [(set (match_operand:SI 0 "s_register_operand" "")
1588 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1589 (match_operand:SI 1 "s_register_operand" "")))]
1590 "TARGET_EITHER"
1591 ""
1592 )
1593
1594 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1595 (define_insn "*arm_mulsi3"
1596 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1597 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1598 (match_operand:SI 1 "s_register_operand" "%0,r")))]
1599 "TARGET_32BIT && !arm_arch6"
1600 "mul%?\\t%0, %2, %1"
1601 [(set_attr "type" "mul")
1602 (set_attr "predicable" "yes")]
1603 )
1604
1605 (define_insn "*arm_mulsi3_v6"
1606 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1607 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1608 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
1609 "TARGET_32BIT && arm_arch6"
1610 "mul%?\\t%0, %1, %2"
1611 [(set_attr "type" "mul")
1612 (set_attr "predicable" "yes")
1613 (set_attr "arch" "t2,t2,*")
1614 (set_attr "length" "4")
1615 (set_attr "predicable_short_it" "yes,yes,no")]
1616 )
1617
1618 (define_insn "*mulsi3_compare0"
1619 [(set (reg:CC_NOOV CC_REGNUM)
1620 (compare:CC_NOOV (mult:SI
1621 (match_operand:SI 2 "s_register_operand" "r,r")
1622 (match_operand:SI 1 "s_register_operand" "%0,r"))
1623 (const_int 0)))
1624 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1625 (mult:SI (match_dup 2) (match_dup 1)))]
1626 "TARGET_ARM && !arm_arch6"
1627 "muls%?\\t%0, %2, %1"
1628 [(set_attr "conds" "set")
1629 (set_attr "type" "muls")]
1630 )
1631
1632 (define_insn "*mulsi3_compare0_v6"
1633 [(set (reg:CC_NOOV CC_REGNUM)
1634 (compare:CC_NOOV (mult:SI
1635 (match_operand:SI 2 "s_register_operand" "r")
1636 (match_operand:SI 1 "s_register_operand" "r"))
1637 (const_int 0)))
1638 (set (match_operand:SI 0 "s_register_operand" "=r")
1639 (mult:SI (match_dup 2) (match_dup 1)))]
1640 "TARGET_ARM && arm_arch6 && optimize_size"
1641 "muls%?\\t%0, %2, %1"
1642 [(set_attr "conds" "set")
1643 (set_attr "type" "muls")]
1644 )
1645
1646 (define_insn "*mulsi_compare0_scratch"
1647 [(set (reg:CC_NOOV CC_REGNUM)
1648 (compare:CC_NOOV (mult:SI
1649 (match_operand:SI 2 "s_register_operand" "r,r")
1650 (match_operand:SI 1 "s_register_operand" "%0,r"))
1651 (const_int 0)))
1652 (clobber (match_scratch:SI 0 "=&r,&r"))]
1653 "TARGET_ARM && !arm_arch6"
1654 "muls%?\\t%0, %2, %1"
1655 [(set_attr "conds" "set")
1656 (set_attr "type" "muls")]
1657 )
1658
1659 (define_insn "*mulsi_compare0_scratch_v6"
1660 [(set (reg:CC_NOOV CC_REGNUM)
1661 (compare:CC_NOOV (mult:SI
1662 (match_operand:SI 2 "s_register_operand" "r")
1663 (match_operand:SI 1 "s_register_operand" "r"))
1664 (const_int 0)))
1665 (clobber (match_scratch:SI 0 "=r"))]
1666 "TARGET_ARM && arm_arch6 && optimize_size"
1667 "muls%?\\t%0, %2, %1"
1668 [(set_attr "conds" "set")
1669 (set_attr "type" "muls")]
1670 )
1671
1672 ;; Unnamed templates to match MLA instruction.
1673
1674 (define_insn "*mulsi3addsi"
1675 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1676 (plus:SI
1677 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1678 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1679 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1680 "TARGET_32BIT && !arm_arch6"
1681 "mla%?\\t%0, %2, %1, %3"
1682 [(set_attr "type" "mla")
1683 (set_attr "predicable" "yes")]
1684 )
1685
1686 (define_insn "*mulsi3addsi_v6"
1687 [(set (match_operand:SI 0 "s_register_operand" "=r")
1688 (plus:SI
1689 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1690 (match_operand:SI 1 "s_register_operand" "r"))
1691 (match_operand:SI 3 "s_register_operand" "r")))]
1692 "TARGET_32BIT && arm_arch6"
1693 "mla%?\\t%0, %2, %1, %3"
1694 [(set_attr "type" "mla")
1695 (set_attr "predicable" "yes")]
1696 )
1697
1698 (define_insn "*mulsi3addsi_compare0"
1699 [(set (reg:CC_NOOV CC_REGNUM)
1700 (compare:CC_NOOV
1701 (plus:SI (mult:SI
1702 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1703 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1704 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1705 (const_int 0)))
1706 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1707 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1708 (match_dup 3)))]
1709 "TARGET_ARM && arm_arch6"
1710 "mlas%?\\t%0, %2, %1, %3"
1711 [(set_attr "conds" "set")
1712 (set_attr "type" "mlas")]
1713 )
1714
1715 (define_insn "*mulsi3addsi_compare0_v6"
1716 [(set (reg:CC_NOOV CC_REGNUM)
1717 (compare:CC_NOOV
1718 (plus:SI (mult:SI
1719 (match_operand:SI 2 "s_register_operand" "r")
1720 (match_operand:SI 1 "s_register_operand" "r"))
1721 (match_operand:SI 3 "s_register_operand" "r"))
1722 (const_int 0)))
1723 (set (match_operand:SI 0 "s_register_operand" "=r")
1724 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1725 (match_dup 3)))]
1726 "TARGET_ARM && arm_arch6 && optimize_size"
1727 "mlas%?\\t%0, %2, %1, %3"
1728 [(set_attr "conds" "set")
1729 (set_attr "type" "mlas")]
1730 )
1731
1732 (define_insn "*mulsi3addsi_compare0_scratch"
1733 [(set (reg:CC_NOOV CC_REGNUM)
1734 (compare:CC_NOOV
1735 (plus:SI (mult:SI
1736 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1737 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1738 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1739 (const_int 0)))
1740 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1741 "TARGET_ARM && !arm_arch6"
1742 "mlas%?\\t%0, %2, %1, %3"
1743 [(set_attr "conds" "set")
1744 (set_attr "type" "mlas")]
1745 )
1746
1747 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1748 [(set (reg:CC_NOOV CC_REGNUM)
1749 (compare:CC_NOOV
1750 (plus:SI (mult:SI
1751 (match_operand:SI 2 "s_register_operand" "r")
1752 (match_operand:SI 1 "s_register_operand" "r"))
1753 (match_operand:SI 3 "s_register_operand" "r"))
1754 (const_int 0)))
1755 (clobber (match_scratch:SI 0 "=r"))]
1756 "TARGET_ARM && arm_arch6 && optimize_size"
1757 "mlas%?\\t%0, %2, %1, %3"
1758 [(set_attr "conds" "set")
1759 (set_attr "type" "mlas")]
1760 )
1761
1762 (define_insn "*mulsi3subsi"
1763 [(set (match_operand:SI 0 "s_register_operand" "=r")
1764 (minus:SI
1765 (match_operand:SI 3 "s_register_operand" "r")
1766 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1767 (match_operand:SI 1 "s_register_operand" "r"))))]
1768 "TARGET_32BIT && arm_arch_thumb2"
1769 "mls%?\\t%0, %2, %1, %3"
1770 [(set_attr "type" "mla")
1771 (set_attr "predicable" "yes")]
1772 )
1773
1774 (define_expand "maddsidi4"
1775 [(set (match_operand:DI 0 "s_register_operand" "")
1776 (plus:DI
1777 (mult:DI
1778 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1779 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1780 (match_operand:DI 3 "s_register_operand" "")))]
1781 "TARGET_32BIT"
1782 "")
1783
1784 (define_insn "*mulsidi3adddi"
1785 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1786 (plus:DI
1787 (mult:DI
1788 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1789 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1790 (match_operand:DI 1 "s_register_operand" "0")))]
1791 "TARGET_32BIT && !arm_arch6"
1792 "smlal%?\\t%Q0, %R0, %3, %2"
1793 [(set_attr "type" "smlal")
1794 (set_attr "predicable" "yes")]
1795 )
1796
1797 (define_insn "*mulsidi3adddi_v6"
1798 [(set (match_operand:DI 0 "s_register_operand" "=r")
1799 (plus:DI
1800 (mult:DI
1801 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1802 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1803 (match_operand:DI 1 "s_register_operand" "0")))]
1804 "TARGET_32BIT && arm_arch6"
1805 "smlal%?\\t%Q0, %R0, %3, %2"
1806 [(set_attr "type" "smlal")
1807 (set_attr "predicable" "yes")]
1808 )
1809
1810 ;; 32x32->64 widening multiply.
1811 ;; As with mulsi3, the only difference between the v3-5 and v6+
1812 ;; versions of these patterns is the requirement that the output not
1813 ;; overlap the inputs, but that still means we have to have a named
1814 ;; expander and two different starred insns.
1815
1816 (define_expand "mulsidi3"
1817 [(set (match_operand:DI 0 "s_register_operand" "")
1818 (mult:DI
1819 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1820 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1821 "TARGET_32BIT"
1822 ""
1823 )
1824
1825 (define_insn "*mulsidi3_nov6"
1826 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1827 (mult:DI
1828 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1829 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1830 "TARGET_32BIT && !arm_arch6"
1831 "smull%?\\t%Q0, %R0, %1, %2"
1832 [(set_attr "type" "smull")
1833 (set_attr "predicable" "yes")]
1834 )
1835
1836 (define_insn "*mulsidi3_v6"
1837 [(set (match_operand:DI 0 "s_register_operand" "=r")
1838 (mult:DI
1839 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1840 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1841 "TARGET_32BIT && arm_arch6"
1842 "smull%?\\t%Q0, %R0, %1, %2"
1843 [(set_attr "type" "smull")
1844 (set_attr "predicable" "yes")]
1845 )
1846
1847 (define_expand "umulsidi3"
1848 [(set (match_operand:DI 0 "s_register_operand" "")
1849 (mult:DI
1850 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1851 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1852 "TARGET_32BIT"
1853 ""
1854 )
1855
1856 (define_insn "*umulsidi3_nov6"
1857 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1858 (mult:DI
1859 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1860 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1861 "TARGET_32BIT && !arm_arch6"
1862 "umull%?\\t%Q0, %R0, %1, %2"
1863 [(set_attr "type" "umull")
1864 (set_attr "predicable" "yes")]
1865 )
1866
1867 (define_insn "*umulsidi3_v6"
1868 [(set (match_operand:DI 0 "s_register_operand" "=r")
1869 (mult:DI
1870 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1871 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1872 "TARGET_32BIT && arm_arch6"
1873 "umull%?\\t%Q0, %R0, %1, %2"
1874 [(set_attr "type" "umull")
1875 (set_attr "predicable" "yes")]
1876 )
1877
1878 (define_expand "umaddsidi4"
1879 [(set (match_operand:DI 0 "s_register_operand" "")
1880 (plus:DI
1881 (mult:DI
1882 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1883 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1884 (match_operand:DI 3 "s_register_operand" "")))]
1885 "TARGET_32BIT"
1886 "")
1887
1888 (define_insn "*umulsidi3adddi"
1889 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1890 (plus:DI
1891 (mult:DI
1892 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1893 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1894 (match_operand:DI 1 "s_register_operand" "0")))]
1895 "TARGET_32BIT && !arm_arch6"
1896 "umlal%?\\t%Q0, %R0, %3, %2"
1897 [(set_attr "type" "umlal")
1898 (set_attr "predicable" "yes")]
1899 )
1900
1901 (define_insn "*umulsidi3adddi_v6"
1902 [(set (match_operand:DI 0 "s_register_operand" "=r")
1903 (plus:DI
1904 (mult:DI
1905 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1906 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1907 (match_operand:DI 1 "s_register_operand" "0")))]
1908 "TARGET_32BIT && arm_arch6"
1909 "umlal%?\\t%Q0, %R0, %3, %2"
1910 [(set_attr "type" "umlal")
1911 (set_attr "predicable" "yes")]
1912 )
1913
1914 (define_expand "smulsi3_highpart"
1915 [(parallel
1916 [(set (match_operand:SI 0 "s_register_operand" "")
1917 (truncate:SI
1918 (lshiftrt:DI
1919 (mult:DI
1920 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1921 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1922 (const_int 32))))
1923 (clobber (match_scratch:SI 3 ""))])]
1924 "TARGET_32BIT"
1925 ""
1926 )
1927
1928 (define_insn "*smulsi3_highpart_nov6"
1929 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1930 (truncate:SI
1931 (lshiftrt:DI
1932 (mult:DI
1933 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1934 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1935 (const_int 32))))
1936 (clobber (match_scratch:SI 3 "=&r,&r"))]
1937 "TARGET_32BIT && !arm_arch6"
1938 "smull%?\\t%3, %0, %2, %1"
1939 [(set_attr "type" "smull")
1940 (set_attr "predicable" "yes")]
1941 )
1942
1943 (define_insn "*smulsi3_highpart_v6"
1944 [(set (match_operand:SI 0 "s_register_operand" "=r")
1945 (truncate:SI
1946 (lshiftrt:DI
1947 (mult:DI
1948 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1949 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1950 (const_int 32))))
1951 (clobber (match_scratch:SI 3 "=r"))]
1952 "TARGET_32BIT && arm_arch6"
1953 "smull%?\\t%3, %0, %2, %1"
1954 [(set_attr "type" "smull")
1955 (set_attr "predicable" "yes")]
1956 )
1957
1958 (define_expand "umulsi3_highpart"
1959 [(parallel
1960 [(set (match_operand:SI 0 "s_register_operand" "")
1961 (truncate:SI
1962 (lshiftrt:DI
1963 (mult:DI
1964 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1965 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1966 (const_int 32))))
1967 (clobber (match_scratch:SI 3 ""))])]
1968 "TARGET_32BIT"
1969 ""
1970 )
1971
1972 (define_insn "*umulsi3_highpart_nov6"
1973 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1974 (truncate:SI
1975 (lshiftrt:DI
1976 (mult:DI
1977 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1978 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1979 (const_int 32))))
1980 (clobber (match_scratch:SI 3 "=&r,&r"))]
1981 "TARGET_32BIT && !arm_arch6"
1982 "umull%?\\t%3, %0, %2, %1"
1983 [(set_attr "type" "umull")
1984 (set_attr "predicable" "yes")]
1985 )
1986
1987 (define_insn "*umulsi3_highpart_v6"
1988 [(set (match_operand:SI 0 "s_register_operand" "=r")
1989 (truncate:SI
1990 (lshiftrt:DI
1991 (mult:DI
1992 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1993 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1994 (const_int 32))))
1995 (clobber (match_scratch:SI 3 "=r"))]
1996 "TARGET_32BIT && arm_arch6"
1997 "umull%?\\t%3, %0, %2, %1"
1998 [(set_attr "type" "umull")
1999 (set_attr "predicable" "yes")]
2000 )
2001
2002 (define_insn "mulhisi3"
2003 [(set (match_operand:SI 0 "s_register_operand" "=r")
2004 (mult:SI (sign_extend:SI
2005 (match_operand:HI 1 "s_register_operand" "%r"))
2006 (sign_extend:SI
2007 (match_operand:HI 2 "s_register_operand" "r"))))]
2008 "TARGET_DSP_MULTIPLY"
2009 "smulbb%?\\t%0, %1, %2"
2010 [(set_attr "type" "smulxy")
2011 (set_attr "predicable" "yes")]
2012 )
2013
2014 (define_insn "*mulhisi3tb"
2015 [(set (match_operand:SI 0 "s_register_operand" "=r")
2016 (mult:SI (ashiftrt:SI
2017 (match_operand:SI 1 "s_register_operand" "r")
2018 (const_int 16))
2019 (sign_extend:SI
2020 (match_operand:HI 2 "s_register_operand" "r"))))]
2021 "TARGET_DSP_MULTIPLY"
2022 "smultb%?\\t%0, %1, %2"
2023 [(set_attr "type" "smulxy")
2024 (set_attr "predicable" "yes")]
2025 )
2026
2027 (define_insn "*mulhisi3bt"
2028 [(set (match_operand:SI 0 "s_register_operand" "=r")
2029 (mult:SI (sign_extend:SI
2030 (match_operand:HI 1 "s_register_operand" "r"))
2031 (ashiftrt:SI
2032 (match_operand:SI 2 "s_register_operand" "r")
2033 (const_int 16))))]
2034 "TARGET_DSP_MULTIPLY"
2035 "smulbt%?\\t%0, %1, %2"
2036 [(set_attr "type" "smulxy")
2037 (set_attr "predicable" "yes")]
2038 )
2039
2040 (define_insn "*mulhisi3tt"
2041 [(set (match_operand:SI 0 "s_register_operand" "=r")
2042 (mult:SI (ashiftrt:SI
2043 (match_operand:SI 1 "s_register_operand" "r")
2044 (const_int 16))
2045 (ashiftrt:SI
2046 (match_operand:SI 2 "s_register_operand" "r")
2047 (const_int 16))))]
2048 "TARGET_DSP_MULTIPLY"
2049 "smultt%?\\t%0, %1, %2"
2050 [(set_attr "type" "smulxy")
2051 (set_attr "predicable" "yes")]
2052 )
2053
2054 (define_insn "maddhisi4"
2055 [(set (match_operand:SI 0 "s_register_operand" "=r")
2056 (plus:SI (mult:SI (sign_extend:SI
2057 (match_operand:HI 1 "s_register_operand" "r"))
2058 (sign_extend:SI
2059 (match_operand:HI 2 "s_register_operand" "r")))
2060 (match_operand:SI 3 "s_register_operand" "r")))]
2061 "TARGET_DSP_MULTIPLY"
2062 "smlabb%?\\t%0, %1, %2, %3"
2063 [(set_attr "type" "smlaxy")
2064 (set_attr "predicable" "yes")]
2065 )
2066
2067 ;; Note: there is no maddhisi4ibt because this one is canonical form
2068 (define_insn "*maddhisi4tb"
2069 [(set (match_operand:SI 0 "s_register_operand" "=r")
2070 (plus:SI (mult:SI (ashiftrt:SI
2071 (match_operand:SI 1 "s_register_operand" "r")
2072 (const_int 16))
2073 (sign_extend:SI
2074 (match_operand:HI 2 "s_register_operand" "r")))
2075 (match_operand:SI 3 "s_register_operand" "r")))]
2076 "TARGET_DSP_MULTIPLY"
2077 "smlatb%?\\t%0, %1, %2, %3"
2078 [(set_attr "type" "smlaxy")
2079 (set_attr "predicable" "yes")]
2080 )
2081
2082 (define_insn "*maddhisi4tt"
2083 [(set (match_operand:SI 0 "s_register_operand" "=r")
2084 (plus:SI (mult:SI (ashiftrt:SI
2085 (match_operand:SI 1 "s_register_operand" "r")
2086 (const_int 16))
2087 (ashiftrt:SI
2088 (match_operand:SI 2 "s_register_operand" "r")
2089 (const_int 16)))
2090 (match_operand:SI 3 "s_register_operand" "r")))]
2091 "TARGET_DSP_MULTIPLY"
2092 "smlatt%?\\t%0, %1, %2, %3"
2093 [(set_attr "type" "smlaxy")
2094 (set_attr "predicable" "yes")]
2095 )
2096
2097 (define_insn "maddhidi4"
2098 [(set (match_operand:DI 0 "s_register_operand" "=r")
2099 (plus:DI
2100 (mult:DI (sign_extend:DI
2101 (match_operand:HI 1 "s_register_operand" "r"))
2102 (sign_extend:DI
2103 (match_operand:HI 2 "s_register_operand" "r")))
2104 (match_operand:DI 3 "s_register_operand" "0")))]
2105 "TARGET_DSP_MULTIPLY"
2106 "smlalbb%?\\t%Q0, %R0, %1, %2"
2107 [(set_attr "type" "smlalxy")
2108 (set_attr "predicable" "yes")])
2109
2110 ;; Note: there is no maddhidi4ibt because this one is canonical form
2111 (define_insn "*maddhidi4tb"
2112 [(set (match_operand:DI 0 "s_register_operand" "=r")
2113 (plus:DI
2114 (mult:DI (sign_extend:DI
2115 (ashiftrt:SI
2116 (match_operand:SI 1 "s_register_operand" "r")
2117 (const_int 16)))
2118 (sign_extend:DI
2119 (match_operand:HI 2 "s_register_operand" "r")))
2120 (match_operand:DI 3 "s_register_operand" "0")))]
2121 "TARGET_DSP_MULTIPLY"
2122 "smlaltb%?\\t%Q0, %R0, %1, %2"
2123 [(set_attr "type" "smlalxy")
2124 (set_attr "predicable" "yes")])
2125
2126 (define_insn "*maddhidi4tt"
2127 [(set (match_operand:DI 0 "s_register_operand" "=r")
2128 (plus:DI
2129 (mult:DI (sign_extend:DI
2130 (ashiftrt:SI
2131 (match_operand:SI 1 "s_register_operand" "r")
2132 (const_int 16)))
2133 (sign_extend:DI
2134 (ashiftrt:SI
2135 (match_operand:SI 2 "s_register_operand" "r")
2136 (const_int 16))))
2137 (match_operand:DI 3 "s_register_operand" "0")))]
2138 "TARGET_DSP_MULTIPLY"
2139 "smlaltt%?\\t%Q0, %R0, %1, %2"
2140 [(set_attr "type" "smlalxy")
2141 (set_attr "predicable" "yes")])
2142
2143 (define_expand "mulsf3"
2144 [(set (match_operand:SF 0 "s_register_operand" "")
2145 (mult:SF (match_operand:SF 1 "s_register_operand" "")
2146 (match_operand:SF 2 "s_register_operand" "")))]
2147 "TARGET_32BIT && TARGET_HARD_FLOAT"
2148 "
2149 ")
2150
2151 (define_expand "muldf3"
2152 [(set (match_operand:DF 0 "s_register_operand" "")
2153 (mult:DF (match_operand:DF 1 "s_register_operand" "")
2154 (match_operand:DF 2 "s_register_operand" "")))]
2155 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
2156 "
2157 ")
2158 \f
2159 ;; Division insns
2160
2161 (define_expand "divsf3"
2162 [(set (match_operand:SF 0 "s_register_operand" "")
2163 (div:SF (match_operand:SF 1 "s_register_operand" "")
2164 (match_operand:SF 2 "s_register_operand" "")))]
2165 "TARGET_32BIT && TARGET_HARD_FLOAT"
2166 "")
2167
2168 (define_expand "divdf3"
2169 [(set (match_operand:DF 0 "s_register_operand" "")
2170 (div:DF (match_operand:DF 1 "s_register_operand" "")
2171 (match_operand:DF 2 "s_register_operand" "")))]
2172 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
2173 "")
2174 \f
2175 ;; Boolean and,ior,xor insns
2176
2177 ;; Split up double word logical operations
2178
2179 ;; Split up simple DImode logical operations. Simply perform the logical
2180 ;; operation on the upper and lower halves of the registers.
2181 (define_split
2182 [(set (match_operand:DI 0 "s_register_operand" "")
2183 (match_operator:DI 6 "logical_binary_operator"
2184 [(match_operand:DI 1 "s_register_operand" "")
2185 (match_operand:DI 2 "s_register_operand" "")]))]
2186 "TARGET_32BIT && reload_completed
2187 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2188 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2189 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2190 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2191 "
2192 {
2193 operands[3] = gen_highpart (SImode, operands[0]);
2194 operands[0] = gen_lowpart (SImode, operands[0]);
2195 operands[4] = gen_highpart (SImode, operands[1]);
2196 operands[1] = gen_lowpart (SImode, operands[1]);
2197 operands[5] = gen_highpart (SImode, operands[2]);
2198 operands[2] = gen_lowpart (SImode, operands[2]);
2199 }"
2200 )
2201
2202 (define_split
2203 [(set (match_operand:DI 0 "s_register_operand" "")
2204 (match_operator:DI 6 "logical_binary_operator"
2205 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2206 (match_operand:DI 1 "s_register_operand" "")]))]
2207 "TARGET_32BIT && reload_completed"
2208 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2209 (set (match_dup 3) (match_op_dup:SI 6
2210 [(ashiftrt:SI (match_dup 2) (const_int 31))
2211 (match_dup 4)]))]
2212 "
2213 {
2214 operands[3] = gen_highpart (SImode, operands[0]);
2215 operands[0] = gen_lowpart (SImode, operands[0]);
2216 operands[4] = gen_highpart (SImode, operands[1]);
2217 operands[1] = gen_lowpart (SImode, operands[1]);
2218 operands[5] = gen_highpart (SImode, operands[2]);
2219 operands[2] = gen_lowpart (SImode, operands[2]);
2220 }"
2221 )
2222
2223 ;; The zero extend of operand 2 means we can just copy the high part of
2224 ;; operand1 into operand0.
2225 (define_split
2226 [(set (match_operand:DI 0 "s_register_operand" "")
2227 (ior:DI
2228 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2229 (match_operand:DI 1 "s_register_operand" "")))]
2230 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2231 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2232 (set (match_dup 3) (match_dup 4))]
2233 "
2234 {
2235 operands[4] = gen_highpart (SImode, operands[1]);
2236 operands[3] = gen_highpart (SImode, operands[0]);
2237 operands[0] = gen_lowpart (SImode, operands[0]);
2238 operands[1] = gen_lowpart (SImode, operands[1]);
2239 }"
2240 )
2241
2242 ;; The zero extend of operand 2 means we can just copy the high part of
2243 ;; operand1 into operand0.
2244 (define_split
2245 [(set (match_operand:DI 0 "s_register_operand" "")
2246 (xor:DI
2247 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2248 (match_operand:DI 1 "s_register_operand" "")))]
2249 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2250 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2251 (set (match_dup 3) (match_dup 4))]
2252 "
2253 {
2254 operands[4] = gen_highpart (SImode, operands[1]);
2255 operands[3] = gen_highpart (SImode, operands[0]);
2256 operands[0] = gen_lowpart (SImode, operands[0]);
2257 operands[1] = gen_lowpart (SImode, operands[1]);
2258 }"
2259 )
2260
2261 (define_expand "anddi3"
2262 [(set (match_operand:DI 0 "s_register_operand" "")
2263 (and:DI (match_operand:DI 1 "s_register_operand" "")
2264 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2265 "TARGET_32BIT"
2266 "
2267 if (!TARGET_NEON && !TARGET_IWMMXT)
2268 {
2269 rtx low = simplify_gen_binary (AND, SImode,
2270 gen_lowpart (SImode, operands[1]),
2271 gen_lowpart (SImode, operands[2]));
2272 rtx high = simplify_gen_binary (AND, SImode,
2273 gen_highpart (SImode, operands[1]),
2274 gen_highpart_mode (SImode, DImode,
2275 operands[2]));
2276
2277 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2278 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2279
2280 DONE;
2281 }
2282 /* Otherwise expand pattern as above. */
2283 "
2284 )
2285
2286 (define_insn_and_split "*anddi3_insn"
2287 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2288 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2289 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
2290 "TARGET_32BIT && !TARGET_IWMMXT"
2291 {
2292 switch (which_alternative)
2293 {
2294 case 0: /* fall through */
2295 case 6: return "vand\t%P0, %P1, %P2";
2296 case 1: /* fall through */
2297 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2298 DImode, 1, VALID_NEON_QREG_MODE (DImode));
2299 case 2:
2300 case 3:
2301 case 4:
2302 case 5: /* fall through */
2303 return "#";
2304 default: gcc_unreachable ();
2305 }
2306 }
2307 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2308 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2309 [(set (match_dup 3) (match_dup 4))
2310 (set (match_dup 5) (match_dup 6))]
2311 "
2312 {
2313 operands[3] = gen_lowpart (SImode, operands[0]);
2314 operands[5] = gen_highpart (SImode, operands[0]);
2315
2316 operands[4] = simplify_gen_binary (AND, SImode,
2317 gen_lowpart (SImode, operands[1]),
2318 gen_lowpart (SImode, operands[2]));
2319 operands[6] = simplify_gen_binary (AND, SImode,
2320 gen_highpart (SImode, operands[1]),
2321 gen_highpart_mode (SImode, DImode, operands[2]));
2322
2323 }"
2324 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2325 multiple,multiple,neon_logic,neon_logic")
2326 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
2327 avoid_neon_for_64bits,avoid_neon_for_64bits")
2328 (set_attr "length" "*,*,8,8,8,8,*,*")
2329 ]
2330 )
2331
2332 (define_insn_and_split "*anddi_zesidi_di"
2333 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2334 (and:DI (zero_extend:DI
2335 (match_operand:SI 2 "s_register_operand" "r,r"))
2336 (match_operand:DI 1 "s_register_operand" "0,r")))]
2337 "TARGET_32BIT"
2338 "#"
2339 "TARGET_32BIT && reload_completed"
2340 ; The zero extend of operand 2 clears the high word of the output
2341 ; operand.
2342 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2343 (set (match_dup 3) (const_int 0))]
2344 "
2345 {
2346 operands[3] = gen_highpart (SImode, operands[0]);
2347 operands[0] = gen_lowpart (SImode, operands[0]);
2348 operands[1] = gen_lowpart (SImode, operands[1]);
2349 }"
2350 [(set_attr "length" "8")
2351 (set_attr "type" "multiple")]
2352 )
2353
2354 (define_insn "*anddi_sesdi_di"
2355 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2356 (and:DI (sign_extend:DI
2357 (match_operand:SI 2 "s_register_operand" "r,r"))
2358 (match_operand:DI 1 "s_register_operand" "0,r")))]
2359 "TARGET_32BIT"
2360 "#"
2361 [(set_attr "length" "8")
2362 (set_attr "type" "multiple")]
2363 )
2364
2365 (define_expand "andsi3"
2366 [(set (match_operand:SI 0 "s_register_operand" "")
2367 (and:SI (match_operand:SI 1 "s_register_operand" "")
2368 (match_operand:SI 2 "reg_or_int_operand" "")))]
2369 "TARGET_EITHER"
2370 "
2371 if (TARGET_32BIT)
2372 {
2373 if (CONST_INT_P (operands[2]))
2374 {
2375 if (INTVAL (operands[2]) == 255 && arm_arch6)
2376 {
2377 operands[1] = convert_to_mode (QImode, operands[1], 1);
2378 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2379 operands[1]));
2380 DONE;
2381 }
2382 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2383 operands[2] = force_reg (SImode, operands[2]);
2384 else
2385 {
2386 arm_split_constant (AND, SImode, NULL_RTX,
2387 INTVAL (operands[2]), operands[0],
2388 operands[1],
2389 optimize && can_create_pseudo_p ());
2390
2391 DONE;
2392 }
2393 }
2394 }
2395 else /* TARGET_THUMB1 */
2396 {
2397 if (!CONST_INT_P (operands[2]))
2398 {
2399 rtx tmp = force_reg (SImode, operands[2]);
2400 if (rtx_equal_p (operands[0], operands[1]))
2401 operands[2] = tmp;
2402 else
2403 {
2404 operands[2] = operands[1];
2405 operands[1] = tmp;
2406 }
2407 }
2408 else
2409 {
2410 int i;
2411
2412 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2413 {
2414 operands[2] = force_reg (SImode,
2415 GEN_INT (~INTVAL (operands[2])));
2416
2417 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2418
2419 DONE;
2420 }
2421
2422 for (i = 9; i <= 31; i++)
2423 {
2424 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
2425 {
2426 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2427 const0_rtx));
2428 DONE;
2429 }
2430 else if ((HOST_WIDE_INT_1 << i) - 1
2431 == ~INTVAL (operands[2]))
2432 {
2433 rtx shift = GEN_INT (i);
2434 rtx reg = gen_reg_rtx (SImode);
2435
2436 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2437 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2438
2439 DONE;
2440 }
2441 }
2442
2443 operands[2] = force_reg (SImode, operands[2]);
2444 }
2445 }
2446 "
2447 )
2448
2449 ; ??? Check split length for Thumb-2
2450 (define_insn_and_split "*arm_andsi3_insn"
2451 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2452 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2453 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
2454 "TARGET_32BIT"
2455 "@
2456 and%?\\t%0, %1, %2
2457 and%?\\t%0, %1, %2
2458 bic%?\\t%0, %1, #%B2
2459 and%?\\t%0, %1, %2
2460 #"
2461 "TARGET_32BIT
2462 && CONST_INT_P (operands[2])
2463 && !(const_ok_for_arm (INTVAL (operands[2]))
2464 || const_ok_for_arm (~INTVAL (operands[2])))"
2465 [(clobber (const_int 0))]
2466 "
2467 arm_split_constant (AND, SImode, curr_insn,
2468 INTVAL (operands[2]), operands[0], operands[1], 0);
2469 DONE;
2470 "
2471 [(set_attr "length" "4,4,4,4,16")
2472 (set_attr "predicable" "yes")
2473 (set_attr "predicable_short_it" "no,yes,no,no,no")
2474 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
2475 )
2476
2477 (define_insn "*andsi3_compare0"
2478 [(set (reg:CC_NOOV CC_REGNUM)
2479 (compare:CC_NOOV
2480 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2481 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
2482 (const_int 0)))
2483 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2484 (and:SI (match_dup 1) (match_dup 2)))]
2485 "TARGET_32BIT"
2486 "@
2487 ands%?\\t%0, %1, %2
2488 bics%?\\t%0, %1, #%B2
2489 ands%?\\t%0, %1, %2"
2490 [(set_attr "conds" "set")
2491 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2492 )
2493
2494 (define_insn "*andsi3_compare0_scratch"
2495 [(set (reg:CC_NOOV CC_REGNUM)
2496 (compare:CC_NOOV
2497 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2498 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
2499 (const_int 0)))
2500 (clobber (match_scratch:SI 2 "=X,r,X"))]
2501 "TARGET_32BIT"
2502 "@
2503 tst%?\\t%0, %1
2504 bics%?\\t%2, %0, #%B1
2505 tst%?\\t%0, %1"
2506 [(set_attr "conds" "set")
2507 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2508 )
2509
2510 (define_insn "*zeroextractsi_compare0_scratch"
2511 [(set (reg:CC_NOOV CC_REGNUM)
2512 (compare:CC_NOOV (zero_extract:SI
2513 (match_operand:SI 0 "s_register_operand" "r")
2514 (match_operand 1 "const_int_operand" "n")
2515 (match_operand 2 "const_int_operand" "n"))
2516 (const_int 0)))]
2517 "TARGET_32BIT
2518 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2519 && INTVAL (operands[1]) > 0
2520 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2521 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2522 "*
2523 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2524 << INTVAL (operands[2]));
2525 output_asm_insn (\"tst%?\\t%0, %1\", operands);
2526 return \"\";
2527 "
2528 [(set_attr "conds" "set")
2529 (set_attr "predicable" "yes")
2530 (set_attr "type" "logics_imm")]
2531 )
2532
2533 (define_insn_and_split "*ne_zeroextractsi"
2534 [(set (match_operand:SI 0 "s_register_operand" "=r")
2535 (ne:SI (zero_extract:SI
2536 (match_operand:SI 1 "s_register_operand" "r")
2537 (match_operand:SI 2 "const_int_operand" "n")
2538 (match_operand:SI 3 "const_int_operand" "n"))
2539 (const_int 0)))
2540 (clobber (reg:CC CC_REGNUM))]
2541 "TARGET_32BIT
2542 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2543 && INTVAL (operands[2]) > 0
2544 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2545 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2546 "#"
2547 "TARGET_32BIT
2548 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2549 && INTVAL (operands[2]) > 0
2550 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2551 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2552 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2553 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2554 (const_int 0)))
2555 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2556 (set (match_dup 0)
2557 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2558 (match_dup 0) (const_int 1)))]
2559 "
2560 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2561 << INTVAL (operands[3]));
2562 "
2563 [(set_attr "conds" "clob")
2564 (set (attr "length")
2565 (if_then_else (eq_attr "is_thumb" "yes")
2566 (const_int 12)
2567 (const_int 8)))
2568 (set_attr "type" "multiple")]
2569 )
2570
2571 (define_insn_and_split "*ne_zeroextractsi_shifted"
2572 [(set (match_operand:SI 0 "s_register_operand" "=r")
2573 (ne:SI (zero_extract:SI
2574 (match_operand:SI 1 "s_register_operand" "r")
2575 (match_operand:SI 2 "const_int_operand" "n")
2576 (const_int 0))
2577 (const_int 0)))
2578 (clobber (reg:CC CC_REGNUM))]
2579 "TARGET_ARM"
2580 "#"
2581 "TARGET_ARM"
2582 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2583 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2584 (const_int 0)))
2585 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2586 (set (match_dup 0)
2587 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2588 (match_dup 0) (const_int 1)))]
2589 "
2590 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2591 "
2592 [(set_attr "conds" "clob")
2593 (set_attr "length" "8")
2594 (set_attr "type" "multiple")]
2595 )
2596
2597 (define_insn_and_split "*ite_ne_zeroextractsi"
2598 [(set (match_operand:SI 0 "s_register_operand" "=r")
2599 (if_then_else:SI (ne (zero_extract:SI
2600 (match_operand:SI 1 "s_register_operand" "r")
2601 (match_operand:SI 2 "const_int_operand" "n")
2602 (match_operand:SI 3 "const_int_operand" "n"))
2603 (const_int 0))
2604 (match_operand:SI 4 "arm_not_operand" "rIK")
2605 (const_int 0)))
2606 (clobber (reg:CC CC_REGNUM))]
2607 "TARGET_ARM
2608 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2609 && INTVAL (operands[2]) > 0
2610 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2611 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2612 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2613 "#"
2614 "TARGET_ARM
2615 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2616 && INTVAL (operands[2]) > 0
2617 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2618 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2619 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2620 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2621 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2622 (const_int 0)))
2623 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2624 (set (match_dup 0)
2625 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2626 (match_dup 0) (match_dup 4)))]
2627 "
2628 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2629 << INTVAL (operands[3]));
2630 "
2631 [(set_attr "conds" "clob")
2632 (set_attr "length" "8")
2633 (set_attr "type" "multiple")]
2634 )
2635
2636 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2637 [(set (match_operand:SI 0 "s_register_operand" "=r")
2638 (if_then_else:SI (ne (zero_extract:SI
2639 (match_operand:SI 1 "s_register_operand" "r")
2640 (match_operand:SI 2 "const_int_operand" "n")
2641 (const_int 0))
2642 (const_int 0))
2643 (match_operand:SI 3 "arm_not_operand" "rIK")
2644 (const_int 0)))
2645 (clobber (reg:CC CC_REGNUM))]
2646 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2647 "#"
2648 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2649 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2650 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2651 (const_int 0)))
2652 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2653 (set (match_dup 0)
2654 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2655 (match_dup 0) (match_dup 3)))]
2656 "
2657 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2658 "
2659 [(set_attr "conds" "clob")
2660 (set_attr "length" "8")
2661 (set_attr "type" "multiple")]
2662 )
2663
2664 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2665 (define_split
2666 [(set (match_operand:SI 0 "s_register_operand" "")
2667 (match_operator:SI 1 "shiftable_operator"
2668 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2669 (match_operand:SI 3 "const_int_operand" "")
2670 (match_operand:SI 4 "const_int_operand" ""))
2671 (match_operand:SI 5 "s_register_operand" "")]))
2672 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2673 "TARGET_ARM"
2674 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2675 (set (match_dup 0)
2676 (match_op_dup 1
2677 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2678 (match_dup 5)]))]
2679 "{
2680 HOST_WIDE_INT temp = INTVAL (operands[3]);
2681
2682 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2683 operands[4] = GEN_INT (32 - temp);
2684 }"
2685 )
2686
2687 (define_split
2688 [(set (match_operand:SI 0 "s_register_operand" "")
2689 (match_operator:SI 1 "shiftable_operator"
2690 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2691 (match_operand:SI 3 "const_int_operand" "")
2692 (match_operand:SI 4 "const_int_operand" ""))
2693 (match_operand:SI 5 "s_register_operand" "")]))
2694 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2695 "TARGET_ARM"
2696 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2697 (set (match_dup 0)
2698 (match_op_dup 1
2699 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2700 (match_dup 5)]))]
2701 "{
2702 HOST_WIDE_INT temp = INTVAL (operands[3]);
2703
2704 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2705 operands[4] = GEN_INT (32 - temp);
2706 }"
2707 )
2708
2709 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
2710 ;;; represented by the bitfield, then this will produce incorrect results.
2711 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
2712 ;;; which have a real bit-field insert instruction, the truncation happens
2713 ;;; in the bit-field insert instruction itself. Since arm does not have a
2714 ;;; bit-field insert instruction, we would have to emit code here to truncate
2715 ;;; the value before we insert. This loses some of the advantage of having
2716 ;;; this insv pattern, so this pattern needs to be reevalutated.
2717
2718 (define_expand "insv"
2719 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2720 (match_operand 1 "general_operand" "")
2721 (match_operand 2 "general_operand" ""))
2722 (match_operand 3 "reg_or_int_operand" ""))]
2723 "TARGET_ARM || arm_arch_thumb2"
2724 "
2725 {
2726 int start_bit = INTVAL (operands[2]);
2727 int width = INTVAL (operands[1]);
2728 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
2729 rtx target, subtarget;
2730
2731 if (arm_arch_thumb2)
2732 {
2733 if (unaligned_access && MEM_P (operands[0])
2734 && s_register_operand (operands[3], GET_MODE (operands[3]))
2735 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
2736 {
2737 rtx base_addr;
2738
2739 if (BYTES_BIG_ENDIAN)
2740 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2741 - start_bit;
2742
2743 if (width == 32)
2744 {
2745 base_addr = adjust_address (operands[0], SImode,
2746 start_bit / BITS_PER_UNIT);
2747 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
2748 }
2749 else
2750 {
2751 rtx tmp = gen_reg_rtx (HImode);
2752
2753 base_addr = adjust_address (operands[0], HImode,
2754 start_bit / BITS_PER_UNIT);
2755 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2756 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2757 }
2758 DONE;
2759 }
2760 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
2761 {
2762 bool use_bfi = TRUE;
2763
2764 if (CONST_INT_P (operands[3]))
2765 {
2766 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2767
2768 if (val == 0)
2769 {
2770 emit_insn (gen_insv_zero (operands[0], operands[1],
2771 operands[2]));
2772 DONE;
2773 }
2774
2775 /* See if the set can be done with a single orr instruction. */
2776 if (val == mask && const_ok_for_arm (val << start_bit))
2777 use_bfi = FALSE;
2778 }
2779
2780 if (use_bfi)
2781 {
2782 if (!REG_P (operands[3]))
2783 operands[3] = force_reg (SImode, operands[3]);
2784
2785 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2786 operands[3]));
2787 DONE;
2788 }
2789 }
2790 else
2791 FAIL;
2792 }
2793
2794 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2795 FAIL;
2796
2797 target = copy_rtx (operands[0]);
2798 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2799 subreg as the final target. */
2800 if (GET_CODE (target) == SUBREG)
2801 {
2802 subtarget = gen_reg_rtx (SImode);
2803 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2804 < GET_MODE_SIZE (SImode))
2805 target = SUBREG_REG (target);
2806 }
2807 else
2808 subtarget = target;
2809
2810 if (CONST_INT_P (operands[3]))
2811 {
2812 /* Since we are inserting a known constant, we may be able to
2813 reduce the number of bits that we have to clear so that
2814 the mask becomes simple. */
2815 /* ??? This code does not check to see if the new mask is actually
2816 simpler. It may not be. */
2817 rtx op1 = gen_reg_rtx (SImode);
2818 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2819 start of this pattern. */
2820 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2821 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2822
2823 emit_insn (gen_andsi3 (op1, operands[0],
2824 gen_int_mode (~mask2, SImode)));
2825 emit_insn (gen_iorsi3 (subtarget, op1,
2826 gen_int_mode (op3_value << start_bit, SImode)));
2827 }
2828 else if (start_bit == 0
2829 && !(const_ok_for_arm (mask)
2830 || const_ok_for_arm (~mask)))
2831 {
2832 /* A Trick, since we are setting the bottom bits in the word,
2833 we can shift operand[3] up, operand[0] down, OR them together
2834 and rotate the result back again. This takes 3 insns, and
2835 the third might be mergeable into another op. */
2836 /* The shift up copes with the possibility that operand[3] is
2837 wider than the bitfield. */
2838 rtx op0 = gen_reg_rtx (SImode);
2839 rtx op1 = gen_reg_rtx (SImode);
2840
2841 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2842 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2843 emit_insn (gen_iorsi3 (op1, op1, op0));
2844 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2845 }
2846 else if ((width + start_bit == 32)
2847 && !(const_ok_for_arm (mask)
2848 || const_ok_for_arm (~mask)))
2849 {
2850 /* Similar trick, but slightly less efficient. */
2851
2852 rtx op0 = gen_reg_rtx (SImode);
2853 rtx op1 = gen_reg_rtx (SImode);
2854
2855 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2856 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2857 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2858 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2859 }
2860 else
2861 {
2862 rtx op0 = gen_int_mode (mask, SImode);
2863 rtx op1 = gen_reg_rtx (SImode);
2864 rtx op2 = gen_reg_rtx (SImode);
2865
2866 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2867 {
2868 rtx tmp = gen_reg_rtx (SImode);
2869
2870 emit_insn (gen_movsi (tmp, op0));
2871 op0 = tmp;
2872 }
2873
2874 /* Mask out any bits in operand[3] that are not needed. */
2875 emit_insn (gen_andsi3 (op1, operands[3], op0));
2876
2877 if (CONST_INT_P (op0)
2878 && (const_ok_for_arm (mask << start_bit)
2879 || const_ok_for_arm (~(mask << start_bit))))
2880 {
2881 op0 = gen_int_mode (~(mask << start_bit), SImode);
2882 emit_insn (gen_andsi3 (op2, operands[0], op0));
2883 }
2884 else
2885 {
2886 if (CONST_INT_P (op0))
2887 {
2888 rtx tmp = gen_reg_rtx (SImode);
2889
2890 emit_insn (gen_movsi (tmp, op0));
2891 op0 = tmp;
2892 }
2893
2894 if (start_bit != 0)
2895 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2896
2897 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2898 }
2899
2900 if (start_bit != 0)
2901 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2902
2903 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2904 }
2905
2906 if (subtarget != target)
2907 {
2908 /* If TARGET is still a SUBREG, then it must be wider than a word,
2909 so we must be careful only to set the subword we were asked to. */
2910 if (GET_CODE (target) == SUBREG)
2911 emit_move_insn (target, subtarget);
2912 else
2913 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2914 }
2915
2916 DONE;
2917 }"
2918 )
2919
2920 (define_insn "insv_zero"
2921 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2922 (match_operand:SI 1 "const_int_M_operand" "M")
2923 (match_operand:SI 2 "const_int_M_operand" "M"))
2924 (const_int 0))]
2925 "arm_arch_thumb2"
2926 "bfc%?\t%0, %2, %1"
2927 [(set_attr "length" "4")
2928 (set_attr "predicable" "yes")
2929 (set_attr "type" "bfm")]
2930 )
2931
2932 (define_insn "insv_t2"
2933 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2934 (match_operand:SI 1 "const_int_M_operand" "M")
2935 (match_operand:SI 2 "const_int_M_operand" "M"))
2936 (match_operand:SI 3 "s_register_operand" "r"))]
2937 "arm_arch_thumb2"
2938 "bfi%?\t%0, %3, %2, %1"
2939 [(set_attr "length" "4")
2940 (set_attr "predicable" "yes")
2941 (set_attr "type" "bfm")]
2942 )
2943
2944 ; constants for op 2 will never be given to these patterns.
2945 (define_insn_and_split "*anddi_notdi_di"
2946 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2947 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2948 (match_operand:DI 2 "s_register_operand" "r,0")))]
2949 "TARGET_32BIT"
2950 "#"
2951 "TARGET_32BIT && reload_completed
2952 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2953 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2954 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2955 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2956 "
2957 {
2958 operands[3] = gen_highpart (SImode, operands[0]);
2959 operands[0] = gen_lowpart (SImode, operands[0]);
2960 operands[4] = gen_highpart (SImode, operands[1]);
2961 operands[1] = gen_lowpart (SImode, operands[1]);
2962 operands[5] = gen_highpart (SImode, operands[2]);
2963 operands[2] = gen_lowpart (SImode, operands[2]);
2964 }"
2965 [(set_attr "length" "8")
2966 (set_attr "predicable" "yes")
2967 (set_attr "type" "multiple")]
2968 )
2969
2970 (define_insn_and_split "*anddi_notzesidi_di"
2971 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2972 (and:DI (not:DI (zero_extend:DI
2973 (match_operand:SI 2 "s_register_operand" "r,r")))
2974 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2975 "TARGET_32BIT"
2976 "@
2977 bic%?\\t%Q0, %Q1, %2
2978 #"
2979 ; (not (zero_extend ...)) allows us to just copy the high word from
2980 ; operand1 to operand0.
2981 "TARGET_32BIT
2982 && reload_completed
2983 && operands[0] != operands[1]"
2984 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2985 (set (match_dup 3) (match_dup 4))]
2986 "
2987 {
2988 operands[3] = gen_highpart (SImode, operands[0]);
2989 operands[0] = gen_lowpart (SImode, operands[0]);
2990 operands[4] = gen_highpart (SImode, operands[1]);
2991 operands[1] = gen_lowpart (SImode, operands[1]);
2992 }"
2993 [(set_attr "length" "4,8")
2994 (set_attr "predicable" "yes")
2995 (set_attr "type" "multiple")]
2996 )
2997
2998 (define_insn_and_split "*anddi_notdi_zesidi"
2999 [(set (match_operand:DI 0 "s_register_operand" "=r")
3000 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
3001 (zero_extend:DI
3002 (match_operand:SI 1 "s_register_operand" "r"))))]
3003 "TARGET_32BIT"
3004 "#"
3005 "TARGET_32BIT && reload_completed"
3006 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
3007 (set (match_dup 3) (const_int 0))]
3008 "
3009 {
3010 operands[3] = gen_highpart (SImode, operands[0]);
3011 operands[0] = gen_lowpart (SImode, operands[0]);
3012 operands[2] = gen_lowpart (SImode, operands[2]);
3013 }"
3014 [(set_attr "length" "8")
3015 (set_attr "predicable" "yes")
3016 (set_attr "type" "multiple")]
3017 )
3018
3019 (define_insn_and_split "*anddi_notsesidi_di"
3020 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3021 (and:DI (not:DI (sign_extend:DI
3022 (match_operand:SI 2 "s_register_operand" "r,r")))
3023 (match_operand:DI 1 "s_register_operand" "0,r")))]
3024 "TARGET_32BIT"
3025 "#"
3026 "TARGET_32BIT && reload_completed"
3027 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
3028 (set (match_dup 3) (and:SI (not:SI
3029 (ashiftrt:SI (match_dup 2) (const_int 31)))
3030 (match_dup 4)))]
3031 "
3032 {
3033 operands[3] = gen_highpart (SImode, operands[0]);
3034 operands[0] = gen_lowpart (SImode, operands[0]);
3035 operands[4] = gen_highpart (SImode, operands[1]);
3036 operands[1] = gen_lowpart (SImode, operands[1]);
3037 }"
3038 [(set_attr "length" "8")
3039 (set_attr "predicable" "yes")
3040 (set_attr "type" "multiple")]
3041 )
3042
3043 (define_insn "andsi_notsi_si"
3044 [(set (match_operand:SI 0 "s_register_operand" "=r")
3045 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3046 (match_operand:SI 1 "s_register_operand" "r")))]
3047 "TARGET_32BIT"
3048 "bic%?\\t%0, %1, %2"
3049 [(set_attr "predicable" "yes")
3050 (set_attr "type" "logic_reg")]
3051 )
3052
3053 (define_insn "andsi_not_shiftsi_si"
3054 [(set (match_operand:SI 0 "s_register_operand" "=r")
3055 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3056 [(match_operand:SI 2 "s_register_operand" "r")
3057 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3058 (match_operand:SI 1 "s_register_operand" "r")))]
3059 "TARGET_ARM"
3060 "bic%?\\t%0, %1, %2%S4"
3061 [(set_attr "predicable" "yes")
3062 (set_attr "shift" "2")
3063 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
3064 (const_string "logic_shift_imm")
3065 (const_string "logic_shift_reg")))]
3066 )
3067
3068 ;; Shifted bics pattern used to set up CC status register and not reusing
3069 ;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3070 ;; does not support shift by register.
3071 (define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3072 [(set (reg:CC_NOOV CC_REGNUM)
3073 (compare:CC_NOOV
3074 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3075 [(match_operand:SI 1 "s_register_operand" "r")
3076 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3077 (match_operand:SI 3 "s_register_operand" "r"))
3078 (const_int 0)))
3079 (clobber (match_scratch:SI 4 "=r"))]
3080 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3081 "bics%?\\t%4, %3, %1%S0"
3082 [(set_attr "predicable" "yes")
3083 (set_attr "conds" "set")
3084 (set_attr "shift" "1")
3085 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3086 (const_string "logic_shift_imm")
3087 (const_string "logic_shift_reg")))]
3088 )
3089
3090 ;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3091 ;; getting reused later.
3092 (define_insn "andsi_not_shiftsi_si_scc"
3093 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3094 (compare:CC_NOOV
3095 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3096 [(match_operand:SI 1 "s_register_operand" "r")
3097 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3098 (match_operand:SI 3 "s_register_operand" "r"))
3099 (const_int 0)))
3100 (set (match_operand:SI 4 "s_register_operand" "=r")
3101 (and:SI (not:SI (match_op_dup 0
3102 [(match_dup 1)
3103 (match_dup 2)]))
3104 (match_dup 3)))])]
3105 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3106 "bics%?\\t%4, %3, %1%S0"
3107 [(set_attr "predicable" "yes")
3108 (set_attr "conds" "set")
3109 (set_attr "shift" "1")
3110 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3111 (const_string "logic_shift_imm")
3112 (const_string "logic_shift_reg")))]
3113 )
3114
3115 (define_insn "*andsi_notsi_si_compare0"
3116 [(set (reg:CC_NOOV CC_REGNUM)
3117 (compare:CC_NOOV
3118 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3119 (match_operand:SI 1 "s_register_operand" "r"))
3120 (const_int 0)))
3121 (set (match_operand:SI 0 "s_register_operand" "=r")
3122 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
3123 "TARGET_32BIT"
3124 "bics\\t%0, %1, %2"
3125 [(set_attr "conds" "set")
3126 (set_attr "type" "logics_shift_reg")]
3127 )
3128
3129 (define_insn "*andsi_notsi_si_compare0_scratch"
3130 [(set (reg:CC_NOOV CC_REGNUM)
3131 (compare:CC_NOOV
3132 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3133 (match_operand:SI 1 "s_register_operand" "r"))
3134 (const_int 0)))
3135 (clobber (match_scratch:SI 0 "=r"))]
3136 "TARGET_32BIT"
3137 "bics\\t%0, %1, %2"
3138 [(set_attr "conds" "set")
3139 (set_attr "type" "logics_shift_reg")]
3140 )
3141
3142 (define_expand "iordi3"
3143 [(set (match_operand:DI 0 "s_register_operand" "")
3144 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3145 (match_operand:DI 2 "neon_logic_op2" "")))]
3146 "TARGET_32BIT"
3147 "
3148 if (!TARGET_NEON && !TARGET_IWMMXT)
3149 {
3150 rtx low = simplify_gen_binary (IOR, SImode,
3151 gen_lowpart (SImode, operands[1]),
3152 gen_lowpart (SImode, operands[2]));
3153 rtx high = simplify_gen_binary (IOR, SImode,
3154 gen_highpart (SImode, operands[1]),
3155 gen_highpart_mode (SImode, DImode,
3156 operands[2]));
3157
3158 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3159 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3160
3161 DONE;
3162 }
3163 /* Otherwise expand pattern as above. */
3164 "
3165 )
3166
3167 (define_insn_and_split "*iordi3_insn"
3168 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3169 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
3170 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
3171 "TARGET_32BIT && !TARGET_IWMMXT"
3172 {
3173 switch (which_alternative)
3174 {
3175 case 0: /* fall through */
3176 case 6: return "vorr\t%P0, %P1, %P2";
3177 case 1: /* fall through */
3178 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3179 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3180 case 2:
3181 case 3:
3182 case 4:
3183 case 5:
3184 return "#";
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 (IOR, SImode,
3198 gen_lowpart (SImode, operands[1]),
3199 gen_lowpart (SImode, operands[2]));
3200 operands[6] = simplify_gen_binary (IOR, SImode,
3201 gen_highpart (SImode, operands[1]),
3202 gen_highpart_mode (SImode, DImode, operands[2]));
3203
3204 }"
3205 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3206 multiple,neon_logic,neon_logic")
3207 (set_attr "length" "*,*,8,8,8,8,*,*")
3208 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
3209 )
3210
3211 (define_insn "*iordi_zesidi_di"
3212 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3213 (ior:DI (zero_extend:DI
3214 (match_operand:SI 2 "s_register_operand" "r,r"))
3215 (match_operand:DI 1 "s_register_operand" "0,?r")))]
3216 "TARGET_32BIT"
3217 "@
3218 orr%?\\t%Q0, %Q1, %2
3219 #"
3220 [(set_attr "length" "4,8")
3221 (set_attr "predicable" "yes")
3222 (set_attr "type" "logic_reg,multiple")]
3223 )
3224
3225 (define_insn "*iordi_sesidi_di"
3226 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3227 (ior:DI (sign_extend:DI
3228 (match_operand:SI 2 "s_register_operand" "r,r"))
3229 (match_operand:DI 1 "s_register_operand" "0,r")))]
3230 "TARGET_32BIT"
3231 "#"
3232 [(set_attr "length" "8")
3233 (set_attr "predicable" "yes")
3234 (set_attr "type" "multiple")]
3235 )
3236
3237 (define_expand "iorsi3"
3238 [(set (match_operand:SI 0 "s_register_operand" "")
3239 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3240 (match_operand:SI 2 "reg_or_int_operand" "")))]
3241 "TARGET_EITHER"
3242 "
3243 if (CONST_INT_P (operands[2]))
3244 {
3245 if (TARGET_32BIT)
3246 {
3247 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3248 operands[2] = force_reg (SImode, operands[2]);
3249 else
3250 {
3251 arm_split_constant (IOR, SImode, NULL_RTX,
3252 INTVAL (operands[2]), operands[0],
3253 operands[1],
3254 optimize && can_create_pseudo_p ());
3255 DONE;
3256 }
3257 }
3258 else /* TARGET_THUMB1 */
3259 {
3260 rtx tmp = force_reg (SImode, operands[2]);
3261 if (rtx_equal_p (operands[0], operands[1]))
3262 operands[2] = tmp;
3263 else
3264 {
3265 operands[2] = operands[1];
3266 operands[1] = tmp;
3267 }
3268 }
3269 }
3270 "
3271 )
3272
3273 (define_insn_and_split "*iorsi3_insn"
3274 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3275 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3276 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
3277 "TARGET_32BIT"
3278 "@
3279 orr%?\\t%0, %1, %2
3280 orr%?\\t%0, %1, %2
3281 orn%?\\t%0, %1, #%B2
3282 orr%?\\t%0, %1, %2
3283 #"
3284 "TARGET_32BIT
3285 && CONST_INT_P (operands[2])
3286 && !(const_ok_for_arm (INTVAL (operands[2]))
3287 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
3288 [(clobber (const_int 0))]
3289 {
3290 arm_split_constant (IOR, SImode, curr_insn,
3291 INTVAL (operands[2]), operands[0], operands[1], 0);
3292 DONE;
3293 }
3294 [(set_attr "length" "4,4,4,4,16")
3295 (set_attr "arch" "32,t2,t2,32,32")
3296 (set_attr "predicable" "yes")
3297 (set_attr "predicable_short_it" "no,yes,no,no,no")
3298 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
3299 )
3300
3301 (define_peephole2
3302 [(match_scratch:SI 3 "r")
3303 (set (match_operand:SI 0 "arm_general_register_operand" "")
3304 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
3305 (match_operand:SI 2 "const_int_operand" "")))]
3306 "TARGET_ARM
3307 && !const_ok_for_arm (INTVAL (operands[2]))
3308 && const_ok_for_arm (~INTVAL (operands[2]))"
3309 [(set (match_dup 3) (match_dup 2))
3310 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3311 ""
3312 )
3313
3314 (define_insn "*iorsi3_compare0"
3315 [(set (reg:CC_NOOV CC_REGNUM)
3316 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3317 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
3318 (const_int 0)))
3319 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3320 (ior:SI (match_dup 1) (match_dup 2)))]
3321 "TARGET_32BIT"
3322 "orrs%?\\t%0, %1, %2"
3323 [(set_attr "conds" "set")
3324 (set_attr "type" "logics_imm,logics_reg")]
3325 )
3326
3327 (define_insn "*iorsi3_compare0_scratch"
3328 [(set (reg:CC_NOOV CC_REGNUM)
3329 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3330 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
3331 (const_int 0)))
3332 (clobber (match_scratch:SI 0 "=r,r"))]
3333 "TARGET_32BIT"
3334 "orrs%?\\t%0, %1, %2"
3335 [(set_attr "conds" "set")
3336 (set_attr "type" "logics_imm,logics_reg")]
3337 )
3338
3339 (define_expand "xordi3"
3340 [(set (match_operand:DI 0 "s_register_operand" "")
3341 (xor:DI (match_operand:DI 1 "s_register_operand" "")
3342 (match_operand:DI 2 "arm_xordi_operand" "")))]
3343 "TARGET_32BIT"
3344 {
3345 /* The iWMMXt pattern for xordi3 accepts only register operands but we want
3346 to reuse this expander for all TARGET_32BIT targets so just force the
3347 constants into a register. Unlike for the anddi3 and iordi3 there are
3348 no NEON instructions that take an immediate. */
3349 if (TARGET_IWMMXT && !REG_P (operands[2]))
3350 operands[2] = force_reg (DImode, operands[2]);
3351 if (!TARGET_NEON && !TARGET_IWMMXT)
3352 {
3353 rtx low = simplify_gen_binary (XOR, SImode,
3354 gen_lowpart (SImode, operands[1]),
3355 gen_lowpart (SImode, operands[2]));
3356 rtx high = simplify_gen_binary (XOR, SImode,
3357 gen_highpart (SImode, operands[1]),
3358 gen_highpart_mode (SImode, DImode,
3359 operands[2]));
3360
3361 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
3362 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
3363
3364 DONE;
3365 }
3366 /* Otherwise expand pattern as above. */
3367 }
3368 )
3369
3370 (define_insn_and_split "*xordi3_insn"
3371 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
3372 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
3373 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3374 "TARGET_32BIT && !TARGET_IWMMXT"
3375 {
3376 switch (which_alternative)
3377 {
3378 case 1:
3379 case 2:
3380 case 3:
3381 case 4: /* fall through */
3382 return "#";
3383 case 0: /* fall through */
3384 case 5: return "veor\t%P0, %P1, %P2";
3385 default: gcc_unreachable ();
3386 }
3387 }
3388 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3389 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3390 [(set (match_dup 3) (match_dup 4))
3391 (set (match_dup 5) (match_dup 6))]
3392 "
3393 {
3394 operands[3] = gen_lowpart (SImode, operands[0]);
3395 operands[5] = gen_highpart (SImode, operands[0]);
3396
3397 operands[4] = simplify_gen_binary (XOR, SImode,
3398 gen_lowpart (SImode, operands[1]),
3399 gen_lowpart (SImode, operands[2]));
3400 operands[6] = simplify_gen_binary (XOR, SImode,
3401 gen_highpart (SImode, operands[1]),
3402 gen_highpart_mode (SImode, DImode, operands[2]));
3403
3404 }"
3405 [(set_attr "length" "*,8,8,8,8,*")
3406 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
3407 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
3408 )
3409
3410 (define_insn "*xordi_zesidi_di"
3411 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3412 (xor:DI (zero_extend:DI
3413 (match_operand:SI 2 "s_register_operand" "r,r"))
3414 (match_operand:DI 1 "s_register_operand" "0,?r")))]
3415 "TARGET_32BIT"
3416 "@
3417 eor%?\\t%Q0, %Q1, %2
3418 #"
3419 [(set_attr "length" "4,8")
3420 (set_attr "predicable" "yes")
3421 (set_attr "type" "logic_reg")]
3422 )
3423
3424 (define_insn "*xordi_sesidi_di"
3425 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3426 (xor:DI (sign_extend:DI
3427 (match_operand:SI 2 "s_register_operand" "r,r"))
3428 (match_operand:DI 1 "s_register_operand" "0,r")))]
3429 "TARGET_32BIT"
3430 "#"
3431 [(set_attr "length" "8")
3432 (set_attr "predicable" "yes")
3433 (set_attr "type" "multiple")]
3434 )
3435
3436 (define_expand "xorsi3"
3437 [(set (match_operand:SI 0 "s_register_operand" "")
3438 (xor:SI (match_operand:SI 1 "s_register_operand" "")
3439 (match_operand:SI 2 "reg_or_int_operand" "")))]
3440 "TARGET_EITHER"
3441 "if (CONST_INT_P (operands[2]))
3442 {
3443 if (TARGET_32BIT)
3444 {
3445 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3446 operands[2] = force_reg (SImode, operands[2]);
3447 else
3448 {
3449 arm_split_constant (XOR, SImode, NULL_RTX,
3450 INTVAL (operands[2]), operands[0],
3451 operands[1],
3452 optimize && can_create_pseudo_p ());
3453 DONE;
3454 }
3455 }
3456 else /* TARGET_THUMB1 */
3457 {
3458 rtx tmp = force_reg (SImode, operands[2]);
3459 if (rtx_equal_p (operands[0], operands[1]))
3460 operands[2] = tmp;
3461 else
3462 {
3463 operands[2] = operands[1];
3464 operands[1] = tmp;
3465 }
3466 }
3467 }"
3468 )
3469
3470 (define_insn_and_split "*arm_xorsi3"
3471 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3472 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3473 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
3474 "TARGET_32BIT"
3475 "@
3476 eor%?\\t%0, %1, %2
3477 eor%?\\t%0, %1, %2
3478 eor%?\\t%0, %1, %2
3479 #"
3480 "TARGET_32BIT
3481 && CONST_INT_P (operands[2])
3482 && !const_ok_for_arm (INTVAL (operands[2]))"
3483 [(clobber (const_int 0))]
3484 {
3485 arm_split_constant (XOR, SImode, curr_insn,
3486 INTVAL (operands[2]), operands[0], operands[1], 0);
3487 DONE;
3488 }
3489 [(set_attr "length" "4,4,4,16")
3490 (set_attr "predicable" "yes")
3491 (set_attr "predicable_short_it" "no,yes,no,no")
3492 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
3493 )
3494
3495 (define_insn "*xorsi3_compare0"
3496 [(set (reg:CC_NOOV CC_REGNUM)
3497 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3498 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
3499 (const_int 0)))
3500 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3501 (xor:SI (match_dup 1) (match_dup 2)))]
3502 "TARGET_32BIT"
3503 "eors%?\\t%0, %1, %2"
3504 [(set_attr "conds" "set")
3505 (set_attr "type" "logics_imm,logics_reg")]
3506 )
3507
3508 (define_insn "*xorsi3_compare0_scratch"
3509 [(set (reg:CC_NOOV CC_REGNUM)
3510 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3511 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
3512 (const_int 0)))]
3513 "TARGET_32BIT"
3514 "teq%?\\t%0, %1"
3515 [(set_attr "conds" "set")
3516 (set_attr "type" "logics_imm,logics_reg")]
3517 )
3518
3519 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3520 ; (NOT D) we can sometimes merge the final NOT into one of the following
3521 ; insns.
3522
3523 (define_split
3524 [(set (match_operand:SI 0 "s_register_operand" "")
3525 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3526 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3527 (match_operand:SI 3 "arm_rhs_operand" "")))
3528 (clobber (match_operand:SI 4 "s_register_operand" ""))]
3529 "TARGET_32BIT"
3530 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3531 (not:SI (match_dup 3))))
3532 (set (match_dup 0) (not:SI (match_dup 4)))]
3533 ""
3534 )
3535
3536 (define_insn_and_split "*andsi_iorsi3_notsi"
3537 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3538 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3539 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3540 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3541 "TARGET_32BIT"
3542 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3543 "&& reload_completed"
3544 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3545 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3546 {
3547 /* If operands[3] is a constant make sure to fold the NOT into it
3548 to avoid creating a NOT of a CONST_INT. */
3549 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3550 if (CONST_INT_P (not_rtx))
3551 {
3552 operands[4] = operands[0];
3553 operands[5] = not_rtx;
3554 }
3555 else
3556 {
3557 operands[5] = operands[0];
3558 operands[4] = not_rtx;
3559 }
3560 }
3561 [(set_attr "length" "8")
3562 (set_attr "ce_count" "2")
3563 (set_attr "predicable" "yes")
3564 (set_attr "type" "multiple")]
3565 )
3566
3567 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3568 ; insns are available?
3569 (define_split
3570 [(set (match_operand:SI 0 "s_register_operand" "")
3571 (match_operator:SI 1 "logical_binary_operator"
3572 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3573 (match_operand:SI 3 "const_int_operand" "")
3574 (match_operand:SI 4 "const_int_operand" ""))
3575 (match_operator:SI 9 "logical_binary_operator"
3576 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3577 (match_operand:SI 6 "const_int_operand" ""))
3578 (match_operand:SI 7 "s_register_operand" "")])]))
3579 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3580 "TARGET_32BIT
3581 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3582 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3583 [(set (match_dup 8)
3584 (match_op_dup 1
3585 [(ashift:SI (match_dup 2) (match_dup 4))
3586 (match_dup 5)]))
3587 (set (match_dup 0)
3588 (match_op_dup 1
3589 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3590 (match_dup 7)]))]
3591 "
3592 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3593 ")
3594
3595 (define_split
3596 [(set (match_operand:SI 0 "s_register_operand" "")
3597 (match_operator:SI 1 "logical_binary_operator"
3598 [(match_operator:SI 9 "logical_binary_operator"
3599 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3600 (match_operand:SI 6 "const_int_operand" ""))
3601 (match_operand:SI 7 "s_register_operand" "")])
3602 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3603 (match_operand:SI 3 "const_int_operand" "")
3604 (match_operand:SI 4 "const_int_operand" ""))]))
3605 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3606 "TARGET_32BIT
3607 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3608 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3609 [(set (match_dup 8)
3610 (match_op_dup 1
3611 [(ashift:SI (match_dup 2) (match_dup 4))
3612 (match_dup 5)]))
3613 (set (match_dup 0)
3614 (match_op_dup 1
3615 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3616 (match_dup 7)]))]
3617 "
3618 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3619 ")
3620
3621 (define_split
3622 [(set (match_operand:SI 0 "s_register_operand" "")
3623 (match_operator:SI 1 "logical_binary_operator"
3624 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3625 (match_operand:SI 3 "const_int_operand" "")
3626 (match_operand:SI 4 "const_int_operand" ""))
3627 (match_operator:SI 9 "logical_binary_operator"
3628 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3629 (match_operand:SI 6 "const_int_operand" ""))
3630 (match_operand:SI 7 "s_register_operand" "")])]))
3631 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3632 "TARGET_32BIT
3633 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3634 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3635 [(set (match_dup 8)
3636 (match_op_dup 1
3637 [(ashift:SI (match_dup 2) (match_dup 4))
3638 (match_dup 5)]))
3639 (set (match_dup 0)
3640 (match_op_dup 1
3641 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3642 (match_dup 7)]))]
3643 "
3644 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3645 ")
3646
3647 (define_split
3648 [(set (match_operand:SI 0 "s_register_operand" "")
3649 (match_operator:SI 1 "logical_binary_operator"
3650 [(match_operator:SI 9 "logical_binary_operator"
3651 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3652 (match_operand:SI 6 "const_int_operand" ""))
3653 (match_operand:SI 7 "s_register_operand" "")])
3654 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3655 (match_operand:SI 3 "const_int_operand" "")
3656 (match_operand:SI 4 "const_int_operand" ""))]))
3657 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3658 "TARGET_32BIT
3659 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3660 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3661 [(set (match_dup 8)
3662 (match_op_dup 1
3663 [(ashift:SI (match_dup 2) (match_dup 4))
3664 (match_dup 5)]))
3665 (set (match_dup 0)
3666 (match_op_dup 1
3667 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3668 (match_dup 7)]))]
3669 "
3670 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3671 ")
3672 \f
3673
3674 ;; Minimum and maximum insns
3675
3676 (define_expand "smaxsi3"
3677 [(parallel [
3678 (set (match_operand:SI 0 "s_register_operand" "")
3679 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3680 (match_operand:SI 2 "arm_rhs_operand" "")))
3681 (clobber (reg:CC CC_REGNUM))])]
3682 "TARGET_32BIT"
3683 "
3684 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3685 {
3686 /* No need for a clobber of the condition code register here. */
3687 emit_insn (gen_rtx_SET (operands[0],
3688 gen_rtx_SMAX (SImode, operands[1],
3689 operands[2])));
3690 DONE;
3691 }
3692 ")
3693
3694 (define_insn "*smax_0"
3695 [(set (match_operand:SI 0 "s_register_operand" "=r")
3696 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3697 (const_int 0)))]
3698 "TARGET_32BIT"
3699 "bic%?\\t%0, %1, %1, asr #31"
3700 [(set_attr "predicable" "yes")
3701 (set_attr "type" "logic_shift_reg")]
3702 )
3703
3704 (define_insn "*smax_m1"
3705 [(set (match_operand:SI 0 "s_register_operand" "=r")
3706 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3707 (const_int -1)))]
3708 "TARGET_32BIT"
3709 "orr%?\\t%0, %1, %1, asr #31"
3710 [(set_attr "predicable" "yes")
3711 (set_attr "type" "logic_shift_reg")]
3712 )
3713
3714 (define_insn_and_split "*arm_smax_insn"
3715 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3716 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3717 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3718 (clobber (reg:CC CC_REGNUM))]
3719 "TARGET_ARM"
3720 "#"
3721 ; cmp\\t%1, %2\;movlt\\t%0, %2
3722 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3723 "TARGET_ARM"
3724 [(set (reg:CC CC_REGNUM)
3725 (compare:CC (match_dup 1) (match_dup 2)))
3726 (set (match_dup 0)
3727 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3728 (match_dup 1)
3729 (match_dup 2)))]
3730 ""
3731 [(set_attr "conds" "clob")
3732 (set_attr "length" "8,12")
3733 (set_attr "type" "multiple")]
3734 )
3735
3736 (define_expand "sminsi3"
3737 [(parallel [
3738 (set (match_operand:SI 0 "s_register_operand" "")
3739 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3740 (match_operand:SI 2 "arm_rhs_operand" "")))
3741 (clobber (reg:CC CC_REGNUM))])]
3742 "TARGET_32BIT"
3743 "
3744 if (operands[2] == const0_rtx)
3745 {
3746 /* No need for a clobber of the condition code register here. */
3747 emit_insn (gen_rtx_SET (operands[0],
3748 gen_rtx_SMIN (SImode, operands[1],
3749 operands[2])));
3750 DONE;
3751 }
3752 ")
3753
3754 (define_insn "*smin_0"
3755 [(set (match_operand:SI 0 "s_register_operand" "=r")
3756 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3757 (const_int 0)))]
3758 "TARGET_32BIT"
3759 "and%?\\t%0, %1, %1, asr #31"
3760 [(set_attr "predicable" "yes")
3761 (set_attr "type" "logic_shift_reg")]
3762 )
3763
3764 (define_insn_and_split "*arm_smin_insn"
3765 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3766 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3767 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3768 (clobber (reg:CC CC_REGNUM))]
3769 "TARGET_ARM"
3770 "#"
3771 ; cmp\\t%1, %2\;movge\\t%0, %2
3772 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3773 "TARGET_ARM"
3774 [(set (reg:CC CC_REGNUM)
3775 (compare:CC (match_dup 1) (match_dup 2)))
3776 (set (match_dup 0)
3777 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3778 (match_dup 1)
3779 (match_dup 2)))]
3780 ""
3781 [(set_attr "conds" "clob")
3782 (set_attr "length" "8,12")
3783 (set_attr "type" "multiple,multiple")]
3784 )
3785
3786 (define_expand "umaxsi3"
3787 [(parallel [
3788 (set (match_operand:SI 0 "s_register_operand" "")
3789 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3790 (match_operand:SI 2 "arm_rhs_operand" "")))
3791 (clobber (reg:CC CC_REGNUM))])]
3792 "TARGET_32BIT"
3793 ""
3794 )
3795
3796 (define_insn_and_split "*arm_umaxsi3"
3797 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3798 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3799 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3800 (clobber (reg:CC CC_REGNUM))]
3801 "TARGET_ARM"
3802 "#"
3803 ; cmp\\t%1, %2\;movcc\\t%0, %2
3804 ; cmp\\t%1, %2\;movcs\\t%0, %1
3805 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3806 "TARGET_ARM"
3807 [(set (reg:CC CC_REGNUM)
3808 (compare:CC (match_dup 1) (match_dup 2)))
3809 (set (match_dup 0)
3810 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3811 (match_dup 1)
3812 (match_dup 2)))]
3813 ""
3814 [(set_attr "conds" "clob")
3815 (set_attr "length" "8,8,12")
3816 (set_attr "type" "store_4")]
3817 )
3818
3819 (define_expand "uminsi3"
3820 [(parallel [
3821 (set (match_operand:SI 0 "s_register_operand" "")
3822 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3823 (match_operand:SI 2 "arm_rhs_operand" "")))
3824 (clobber (reg:CC CC_REGNUM))])]
3825 "TARGET_32BIT"
3826 ""
3827 )
3828
3829 (define_insn_and_split "*arm_uminsi3"
3830 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3831 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3832 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3833 (clobber (reg:CC CC_REGNUM))]
3834 "TARGET_ARM"
3835 "#"
3836 ; cmp\\t%1, %2\;movcs\\t%0, %2
3837 ; cmp\\t%1, %2\;movcc\\t%0, %1
3838 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3839 "TARGET_ARM"
3840 [(set (reg:CC CC_REGNUM)
3841 (compare:CC (match_dup 1) (match_dup 2)))
3842 (set (match_dup 0)
3843 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3844 (match_dup 1)
3845 (match_dup 2)))]
3846 ""
3847 [(set_attr "conds" "clob")
3848 (set_attr "length" "8,8,12")
3849 (set_attr "type" "store_4")]
3850 )
3851
3852 (define_insn "*store_minmaxsi"
3853 [(set (match_operand:SI 0 "memory_operand" "=m")
3854 (match_operator:SI 3 "minmax_operator"
3855 [(match_operand:SI 1 "s_register_operand" "r")
3856 (match_operand:SI 2 "s_register_operand" "r")]))
3857 (clobber (reg:CC CC_REGNUM))]
3858 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
3859 "*
3860 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3861 operands[1], operands[2]);
3862 output_asm_insn (\"cmp\\t%1, %2\", operands);
3863 if (TARGET_THUMB2)
3864 output_asm_insn (\"ite\t%d3\", operands);
3865 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3866 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3867 return \"\";
3868 "
3869 [(set_attr "conds" "clob")
3870 (set (attr "length")
3871 (if_then_else (eq_attr "is_thumb" "yes")
3872 (const_int 14)
3873 (const_int 12)))
3874 (set_attr "type" "store_4")]
3875 )
3876
3877 ; Reject the frame pointer in operand[1], since reloading this after
3878 ; it has been eliminated can cause carnage.
3879 (define_insn "*minmax_arithsi"
3880 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3881 (match_operator:SI 4 "shiftable_operator"
3882 [(match_operator:SI 5 "minmax_operator"
3883 [(match_operand:SI 2 "s_register_operand" "r,r")
3884 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3885 (match_operand:SI 1 "s_register_operand" "0,?r")]))
3886 (clobber (reg:CC CC_REGNUM))]
3887 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
3888 "*
3889 {
3890 enum rtx_code code = GET_CODE (operands[4]);
3891 bool need_else;
3892
3893 if (which_alternative != 0 || operands[3] != const0_rtx
3894 || (code != PLUS && code != IOR && code != XOR))
3895 need_else = true;
3896 else
3897 need_else = false;
3898
3899 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3900 operands[2], operands[3]);
3901 output_asm_insn (\"cmp\\t%2, %3\", operands);
3902 if (TARGET_THUMB2)
3903 {
3904 if (need_else)
3905 output_asm_insn (\"ite\\t%d5\", operands);
3906 else
3907 output_asm_insn (\"it\\t%d5\", operands);
3908 }
3909 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3910 if (need_else)
3911 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3912 return \"\";
3913 }"
3914 [(set_attr "conds" "clob")
3915 (set (attr "length")
3916 (if_then_else (eq_attr "is_thumb" "yes")
3917 (const_int 14)
3918 (const_int 12)))
3919 (set_attr "type" "multiple")]
3920 )
3921
3922 ; Reject the frame pointer in operand[1], since reloading this after
3923 ; it has been eliminated can cause carnage.
3924 (define_insn_and_split "*minmax_arithsi_non_canon"
3925 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3926 (minus:SI
3927 (match_operand:SI 1 "s_register_operand" "0,?Ts")
3928 (match_operator:SI 4 "minmax_operator"
3929 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3930 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
3931 (clobber (reg:CC CC_REGNUM))]
3932 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3933 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
3934 "#"
3935 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3936 [(set (reg:CC CC_REGNUM)
3937 (compare:CC (match_dup 2) (match_dup 3)))
3938
3939 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3940 (set (match_dup 0)
3941 (minus:SI (match_dup 1)
3942 (match_dup 2))))
3943 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3944 (set (match_dup 0)
3945 (match_dup 6)))]
3946 {
3947 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3948 operands[2], operands[3]);
3949 enum rtx_code rc = minmax_code (operands[4]);
3950 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3951 operands[2], operands[3]);
3952
3953 if (mode == CCFPmode || mode == CCFPEmode)
3954 rc = reverse_condition_maybe_unordered (rc);
3955 else
3956 rc = reverse_condition (rc);
3957 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
3958 if (CONST_INT_P (operands[3]))
3959 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3960 else
3961 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
3962 }
3963 [(set_attr "conds" "clob")
3964 (set (attr "length")
3965 (if_then_else (eq_attr "is_thumb" "yes")
3966 (const_int 14)
3967 (const_int 12)))
3968 (set_attr "type" "multiple")]
3969 )
3970
3971 (define_code_iterator SAT [smin smax])
3972 (define_code_iterator SATrev [smin smax])
3973 (define_code_attr SATlo [(smin "1") (smax "2")])
3974 (define_code_attr SAThi [(smin "2") (smax "1")])
3975
3976 (define_insn "*satsi_<SAT:code>"
3977 [(set (match_operand:SI 0 "s_register_operand" "=r")
3978 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3979 (match_operand:SI 1 "const_int_operand" "i"))
3980 (match_operand:SI 2 "const_int_operand" "i")))]
3981 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3982 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3983 {
3984 int mask;
3985 bool signed_sat;
3986 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3987 &mask, &signed_sat))
3988 gcc_unreachable ();
3989
3990 operands[1] = GEN_INT (mask);
3991 if (signed_sat)
3992 return "ssat%?\t%0, %1, %3";
3993 else
3994 return "usat%?\t%0, %1, %3";
3995 }
3996 [(set_attr "predicable" "yes")
3997 (set_attr "type" "alus_imm")]
3998 )
3999
4000 (define_insn "*satsi_<SAT:code>_shift"
4001 [(set (match_operand:SI 0 "s_register_operand" "=r")
4002 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
4003 [(match_operand:SI 4 "s_register_operand" "r")
4004 (match_operand:SI 5 "const_int_operand" "i")])
4005 (match_operand:SI 1 "const_int_operand" "i"))
4006 (match_operand:SI 2 "const_int_operand" "i")))]
4007 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
4008 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
4009 {
4010 int mask;
4011 bool signed_sat;
4012 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
4013 &mask, &signed_sat))
4014 gcc_unreachable ();
4015
4016 operands[1] = GEN_INT (mask);
4017 if (signed_sat)
4018 return "ssat%?\t%0, %1, %4%S3";
4019 else
4020 return "usat%?\t%0, %1, %4%S3";
4021 }
4022 [(set_attr "predicable" "yes")
4023 (set_attr "shift" "3")
4024 (set_attr "type" "logic_shift_reg")])
4025 \f
4026 ;; Shift and rotation insns
4027
4028 (define_expand "ashldi3"
4029 [(set (match_operand:DI 0 "s_register_operand" "")
4030 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
4031 (match_operand:SI 2 "general_operand" "")))]
4032 "TARGET_32BIT"
4033 "
4034 if (TARGET_NEON)
4035 {
4036 /* Delay the decision whether to use NEON or core-regs until
4037 register allocation. */
4038 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
4039 DONE;
4040 }
4041 else
4042 {
4043 /* Only the NEON case can handle in-memory shift counts. */
4044 if (!reg_or_int_operand (operands[2], SImode))
4045 operands[2] = force_reg (SImode, operands[2]);
4046 }
4047
4048 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
4049 ; /* No special preparation statements; expand pattern as above. */
4050 else
4051 {
4052 rtx scratch1, scratch2;
4053
4054 /* Ideally we should use iwmmxt here if we could know that operands[1]
4055 ends up already living in an iwmmxt register. Otherwise it's
4056 cheaper to have the alternate code being generated than moving
4057 values to iwmmxt regs and back. */
4058
4059 /* Expand operation using core-registers.
4060 'FAIL' would achieve the same thing, but this is a bit smarter. */
4061 scratch1 = gen_reg_rtx (SImode);
4062 scratch2 = gen_reg_rtx (SImode);
4063 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4064 operands[2], scratch1, scratch2);
4065 DONE;
4066 }
4067 "
4068 )
4069
4070 (define_expand "ashlsi3"
4071 [(set (match_operand:SI 0 "s_register_operand" "")
4072 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4073 (match_operand:SI 2 "arm_rhs_operand" "")))]
4074 "TARGET_EITHER"
4075 "
4076 if (CONST_INT_P (operands[2])
4077 && (UINTVAL (operands[2])) > 31)
4078 {
4079 emit_insn (gen_movsi (operands[0], const0_rtx));
4080 DONE;
4081 }
4082 "
4083 )
4084
4085 (define_expand "ashrdi3"
4086 [(set (match_operand:DI 0 "s_register_operand" "")
4087 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4088 (match_operand:SI 2 "reg_or_int_operand" "")))]
4089 "TARGET_32BIT"
4090 "
4091 if (TARGET_NEON)
4092 {
4093 /* Delay the decision whether to use NEON or core-regs until
4094 register allocation. */
4095 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4096 DONE;
4097 }
4098
4099 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
4100 ; /* No special preparation statements; expand pattern as above. */
4101 else
4102 {
4103 rtx scratch1, scratch2;
4104
4105 /* Ideally we should use iwmmxt here if we could know that operands[1]
4106 ends up already living in an iwmmxt register. Otherwise it's
4107 cheaper to have the alternate code being generated than moving
4108 values to iwmmxt regs and back. */
4109
4110 /* Expand operation using core-registers.
4111 'FAIL' would achieve the same thing, but this is a bit smarter. */
4112 scratch1 = gen_reg_rtx (SImode);
4113 scratch2 = gen_reg_rtx (SImode);
4114 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4115 operands[2], scratch1, scratch2);
4116 DONE;
4117 }
4118 "
4119 )
4120
4121 (define_expand "ashrsi3"
4122 [(set (match_operand:SI 0 "s_register_operand" "")
4123 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4124 (match_operand:SI 2 "arm_rhs_operand" "")))]
4125 "TARGET_EITHER"
4126 "
4127 if (CONST_INT_P (operands[2])
4128 && UINTVAL (operands[2]) > 31)
4129 operands[2] = GEN_INT (31);
4130 "
4131 )
4132
4133 (define_expand "lshrdi3"
4134 [(set (match_operand:DI 0 "s_register_operand" "")
4135 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4136 (match_operand:SI 2 "reg_or_int_operand" "")))]
4137 "TARGET_32BIT"
4138 "
4139 if (TARGET_NEON)
4140 {
4141 /* Delay the decision whether to use NEON or core-regs until
4142 register allocation. */
4143 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4144 DONE;
4145 }
4146
4147 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
4148 ; /* No special preparation statements; expand pattern as above. */
4149 else
4150 {
4151 rtx scratch1, scratch2;
4152
4153 /* Ideally we should use iwmmxt here if we could know that operands[1]
4154 ends up already living in an iwmmxt register. Otherwise it's
4155 cheaper to have the alternate code being generated than moving
4156 values to iwmmxt regs and back. */
4157
4158 /* Expand operation using core-registers.
4159 'FAIL' would achieve the same thing, but this is a bit smarter. */
4160 scratch1 = gen_reg_rtx (SImode);
4161 scratch2 = gen_reg_rtx (SImode);
4162 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4163 operands[2], scratch1, scratch2);
4164 DONE;
4165 }
4166 "
4167 )
4168
4169 (define_expand "lshrsi3"
4170 [(set (match_operand:SI 0 "s_register_operand" "")
4171 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4172 (match_operand:SI 2 "arm_rhs_operand" "")))]
4173 "TARGET_EITHER"
4174 "
4175 if (CONST_INT_P (operands[2])
4176 && (UINTVAL (operands[2])) > 31)
4177 {
4178 emit_insn (gen_movsi (operands[0], const0_rtx));
4179 DONE;
4180 }
4181 "
4182 )
4183
4184 (define_expand "rotlsi3"
4185 [(set (match_operand:SI 0 "s_register_operand" "")
4186 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4187 (match_operand:SI 2 "reg_or_int_operand" "")))]
4188 "TARGET_32BIT"
4189 "
4190 if (CONST_INT_P (operands[2]))
4191 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4192 else
4193 {
4194 rtx reg = gen_reg_rtx (SImode);
4195 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4196 operands[2] = reg;
4197 }
4198 "
4199 )
4200
4201 (define_expand "rotrsi3"
4202 [(set (match_operand:SI 0 "s_register_operand" "")
4203 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4204 (match_operand:SI 2 "arm_rhs_operand" "")))]
4205 "TARGET_EITHER"
4206 "
4207 if (TARGET_32BIT)
4208 {
4209 if (CONST_INT_P (operands[2])
4210 && UINTVAL (operands[2]) > 31)
4211 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4212 }
4213 else /* TARGET_THUMB1 */
4214 {
4215 if (CONST_INT_P (operands [2]))
4216 operands [2] = force_reg (SImode, operands[2]);
4217 }
4218 "
4219 )
4220
4221 (define_insn "*arm_shiftsi3"
4222 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
4223 (match_operator:SI 3 "shift_operator"
4224 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4225 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
4226 "TARGET_32BIT"
4227 "* return arm_output_shift(operands, 0);"
4228 [(set_attr "predicable" "yes")
4229 (set_attr "arch" "t2,t2,*,*")
4230 (set_attr "predicable_short_it" "yes,yes,no,no")
4231 (set_attr "length" "4")
4232 (set_attr "shift" "1")
4233 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
4234 )
4235
4236 (define_insn "*shiftsi3_compare0"
4237 [(set (reg:CC_NOOV CC_REGNUM)
4238 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
4239 [(match_operand:SI 1 "s_register_operand" "r,r")
4240 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
4241 (const_int 0)))
4242 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4243 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
4244 "TARGET_32BIT"
4245 "* return arm_output_shift(operands, 1);"
4246 [(set_attr "conds" "set")
4247 (set_attr "shift" "1")
4248 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
4249 )
4250
4251 (define_insn "*shiftsi3_compare0_scratch"
4252 [(set (reg:CC_NOOV CC_REGNUM)
4253 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
4254 [(match_operand:SI 1 "s_register_operand" "r,r")
4255 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
4256 (const_int 0)))
4257 (clobber (match_scratch:SI 0 "=r,r"))]
4258 "TARGET_32BIT"
4259 "* return arm_output_shift(operands, 1);"
4260 [(set_attr "conds" "set")
4261 (set_attr "shift" "1")
4262 (set_attr "type" "shift_imm,shift_reg")]
4263 )
4264
4265 (define_insn "*not_shiftsi"
4266 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4267 (not:SI (match_operator:SI 3 "shift_operator"
4268 [(match_operand:SI 1 "s_register_operand" "r,r")
4269 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4270 "TARGET_32BIT"
4271 "mvn%?\\t%0, %1%S3"
4272 [(set_attr "predicable" "yes")
4273 (set_attr "shift" "1")
4274 (set_attr "arch" "32,a")
4275 (set_attr "type" "mvn_shift,mvn_shift_reg")])
4276
4277 (define_insn "*not_shiftsi_compare0"
4278 [(set (reg:CC_NOOV CC_REGNUM)
4279 (compare:CC_NOOV
4280 (not:SI (match_operator:SI 3 "shift_operator"
4281 [(match_operand:SI 1 "s_register_operand" "r,r")
4282 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4283 (const_int 0)))
4284 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4285 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
4286 "TARGET_32BIT"
4287 "mvns%?\\t%0, %1%S3"
4288 [(set_attr "conds" "set")
4289 (set_attr "shift" "1")
4290 (set_attr "arch" "32,a")
4291 (set_attr "type" "mvn_shift,mvn_shift_reg")])
4292
4293 (define_insn "*not_shiftsi_compare0_scratch"
4294 [(set (reg:CC_NOOV CC_REGNUM)
4295 (compare:CC_NOOV
4296 (not:SI (match_operator:SI 3 "shift_operator"
4297 [(match_operand:SI 1 "s_register_operand" "r,r")
4298 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4299 (const_int 0)))
4300 (clobber (match_scratch:SI 0 "=r,r"))]
4301 "TARGET_32BIT"
4302 "mvns%?\\t%0, %1%S3"
4303 [(set_attr "conds" "set")
4304 (set_attr "shift" "1")
4305 (set_attr "arch" "32,a")
4306 (set_attr "type" "mvn_shift,mvn_shift_reg")])
4307
4308 ;; We don't really have extzv, but defining this using shifts helps
4309 ;; to reduce register pressure later on.
4310
4311 (define_expand "extzv"
4312 [(set (match_operand 0 "s_register_operand" "")
4313 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4314 (match_operand 2 "const_int_operand" "")
4315 (match_operand 3 "const_int_operand" "")))]
4316 "TARGET_THUMB1 || arm_arch_thumb2"
4317 "
4318 {
4319 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4320 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4321
4322 if (arm_arch_thumb2)
4323 {
4324 HOST_WIDE_INT width = INTVAL (operands[2]);
4325 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4326
4327 if (unaligned_access && MEM_P (operands[1])
4328 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4329 {
4330 rtx base_addr;
4331
4332 if (BYTES_BIG_ENDIAN)
4333 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4334 - bitpos;
4335
4336 if (width == 32)
4337 {
4338 base_addr = adjust_address (operands[1], SImode,
4339 bitpos / BITS_PER_UNIT);
4340 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4341 }
4342 else
4343 {
4344 rtx dest = operands[0];
4345 rtx tmp = gen_reg_rtx (SImode);
4346
4347 /* We may get a paradoxical subreg here. Strip it off. */
4348 if (GET_CODE (dest) == SUBREG
4349 && GET_MODE (dest) == SImode
4350 && GET_MODE (SUBREG_REG (dest)) == HImode)
4351 dest = SUBREG_REG (dest);
4352
4353 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4354 FAIL;
4355
4356 base_addr = adjust_address (operands[1], HImode,
4357 bitpos / BITS_PER_UNIT);
4358 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4359 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4360 }
4361 DONE;
4362 }
4363 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4364 {
4365 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4366 operands[3]));
4367 DONE;
4368 }
4369 else
4370 FAIL;
4371 }
4372
4373 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4374 FAIL;
4375
4376 operands[3] = GEN_INT (rshift);
4377
4378 if (lshift == 0)
4379 {
4380 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4381 DONE;
4382 }
4383
4384 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4385 operands[3], gen_reg_rtx (SImode)));
4386 DONE;
4387 }"
4388 )
4389
4390 ;; Helper for extzv, for the Thumb-1 register-shifts case.
4391
4392 (define_expand "extzv_t1"
4393 [(set (match_operand:SI 4 "s_register_operand" "")
4394 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4395 (match_operand:SI 2 "const_int_operand" "")))
4396 (set (match_operand:SI 0 "s_register_operand" "")
4397 (lshiftrt:SI (match_dup 4)
4398 (match_operand:SI 3 "const_int_operand" "")))]
4399 "TARGET_THUMB1"
4400 "")
4401
4402 (define_expand "extv"
4403 [(set (match_operand 0 "s_register_operand" "")
4404 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4405 (match_operand 2 "const_int_operand" "")
4406 (match_operand 3 "const_int_operand" "")))]
4407 "arm_arch_thumb2"
4408 {
4409 HOST_WIDE_INT width = INTVAL (operands[2]);
4410 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4411
4412 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4413 && (bitpos % BITS_PER_UNIT) == 0)
4414 {
4415 rtx base_addr;
4416
4417 if (BYTES_BIG_ENDIAN)
4418 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4419
4420 if (width == 32)
4421 {
4422 base_addr = adjust_address (operands[1], SImode,
4423 bitpos / BITS_PER_UNIT);
4424 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4425 }
4426 else
4427 {
4428 rtx dest = operands[0];
4429 rtx tmp = gen_reg_rtx (SImode);
4430
4431 /* We may get a paradoxical subreg here. Strip it off. */
4432 if (GET_CODE (dest) == SUBREG
4433 && GET_MODE (dest) == SImode
4434 && GET_MODE (SUBREG_REG (dest)) == HImode)
4435 dest = SUBREG_REG (dest);
4436
4437 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4438 FAIL;
4439
4440 base_addr = adjust_address (operands[1], HImode,
4441 bitpos / BITS_PER_UNIT);
4442 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4443 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4444 }
4445
4446 DONE;
4447 }
4448 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4449 FAIL;
4450 else if (GET_MODE (operands[0]) == SImode
4451 && GET_MODE (operands[1]) == SImode)
4452 {
4453 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4454 operands[3]));
4455 DONE;
4456 }
4457
4458 FAIL;
4459 })
4460
4461 ; Helper to expand register forms of extv with the proper modes.
4462
4463 (define_expand "extv_regsi"
4464 [(set (match_operand:SI 0 "s_register_operand" "")
4465 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4466 (match_operand 2 "const_int_operand" "")
4467 (match_operand 3 "const_int_operand" "")))]
4468 ""
4469 {
4470 })
4471
4472 ; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4473
4474 (define_insn "unaligned_loadsi"
4475 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4476 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4477 UNSPEC_UNALIGNED_LOAD))]
4478 "unaligned_access"
4479 "ldr%?\t%0, %1\t@ unaligned"
4480 [(set_attr "arch" "t2,any")
4481 (set_attr "length" "2,4")
4482 (set_attr "predicable" "yes")
4483 (set_attr "predicable_short_it" "yes,no")
4484 (set_attr "type" "load_4")])
4485
4486 (define_insn "unaligned_loadhis"
4487 [(set (match_operand:SI 0 "s_register_operand" "=r")
4488 (sign_extend:SI
4489 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
4490 UNSPEC_UNALIGNED_LOAD)))]
4491 "unaligned_access"
4492 "ldrsh%?\t%0, %1\t@ unaligned"
4493 [(set_attr "predicable" "yes")
4494 (set_attr "type" "load_byte")])
4495
4496 (define_insn "unaligned_loadhiu"
4497 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4498 (zero_extend:SI
4499 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4500 UNSPEC_UNALIGNED_LOAD)))]
4501 "unaligned_access"
4502 "ldrh%?\t%0, %1\t@ unaligned"
4503 [(set_attr "arch" "t2,any")
4504 (set_attr "length" "2,4")
4505 (set_attr "predicable" "yes")
4506 (set_attr "predicable_short_it" "yes,no")
4507 (set_attr "type" "load_byte")])
4508
4509 (define_insn "unaligned_storesi"
4510 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4511 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4512 UNSPEC_UNALIGNED_STORE))]
4513 "unaligned_access"
4514 "str%?\t%1, %0\t@ unaligned"
4515 [(set_attr "arch" "t2,any")
4516 (set_attr "length" "2,4")
4517 (set_attr "predicable" "yes")
4518 (set_attr "predicable_short_it" "yes,no")
4519 (set_attr "type" "store_4")])
4520
4521 (define_insn "unaligned_storehi"
4522 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4523 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4524 UNSPEC_UNALIGNED_STORE))]
4525 "unaligned_access"
4526 "strh%?\t%1, %0\t@ unaligned"
4527 [(set_attr "arch" "t2,any")
4528 (set_attr "length" "2,4")
4529 (set_attr "predicable" "yes")
4530 (set_attr "predicable_short_it" "yes,no")
4531 (set_attr "type" "store_4")])
4532
4533
4534 (define_insn "*extv_reg"
4535 [(set (match_operand:SI 0 "s_register_operand" "=r")
4536 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4537 (match_operand:SI 2 "const_int_operand" "n")
4538 (match_operand:SI 3 "const_int_operand" "n")))]
4539 "arm_arch_thumb2
4540 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4541 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
4542 "sbfx%?\t%0, %1, %3, %2"
4543 [(set_attr "length" "4")
4544 (set_attr "predicable" "yes")
4545 (set_attr "type" "bfm")]
4546 )
4547
4548 (define_insn "extzv_t2"
4549 [(set (match_operand:SI 0 "s_register_operand" "=r")
4550 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4551 (match_operand:SI 2 "const_int_operand" "n")
4552 (match_operand:SI 3 "const_int_operand" "n")))]
4553 "arm_arch_thumb2
4554 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4555 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
4556 "ubfx%?\t%0, %1, %3, %2"
4557 [(set_attr "length" "4")
4558 (set_attr "predicable" "yes")
4559 (set_attr "type" "bfm")]
4560 )
4561
4562
4563 ;; Division instructions
4564 (define_insn "divsi3"
4565 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4566 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4567 (match_operand:SI 2 "s_register_operand" "r,r")))]
4568 "TARGET_IDIV"
4569 "@
4570 sdiv%?\t%0, %1, %2
4571 sdiv\t%0, %1, %2"
4572 [(set_attr "arch" "32,v8mb")
4573 (set_attr "predicable" "yes")
4574 (set_attr "type" "sdiv")]
4575 )
4576
4577 (define_insn "udivsi3"
4578 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4579 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4580 (match_operand:SI 2 "s_register_operand" "r,r")))]
4581 "TARGET_IDIV"
4582 "@
4583 udiv%?\t%0, %1, %2
4584 udiv\t%0, %1, %2"
4585 [(set_attr "arch" "32,v8mb")
4586 (set_attr "predicable" "yes")
4587 (set_attr "type" "udiv")]
4588 )
4589
4590 \f
4591 ;; Unary arithmetic insns
4592
4593 (define_expand "negvsi3"
4594 [(match_operand:SI 0 "register_operand")
4595 (match_operand:SI 1 "register_operand")
4596 (match_operand 2 "")]
4597 "TARGET_32BIT"
4598 {
4599 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4600 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4601
4602 DONE;
4603 })
4604
4605 (define_expand "negvdi3"
4606 [(match_operand:DI 0 "register_operand")
4607 (match_operand:DI 1 "register_operand")
4608 (match_operand 2 "")]
4609 "TARGET_ARM"
4610 {
4611 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4612 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4613
4614 DONE;
4615 })
4616
4617
4618 (define_insn_and_split "negdi2_compare"
4619 [(set (reg:CC CC_REGNUM)
4620 (compare:CC
4621 (const_int 0)
4622 (match_operand:DI 1 "register_operand" "0,r")))
4623 (set (match_operand:DI 0 "register_operand" "=r,&r")
4624 (minus:DI (const_int 0) (match_dup 1)))]
4625 "TARGET_ARM"
4626 "#"
4627 "&& reload_completed"
4628 [(parallel [(set (reg:CC CC_REGNUM)
4629 (compare:CC (const_int 0) (match_dup 1)))
4630 (set (match_dup 0) (minus:SI (const_int 0)
4631 (match_dup 1)))])
4632 (parallel [(set (reg:CC CC_REGNUM)
4633 (compare:CC (const_int 0) (match_dup 3)))
4634 (set (match_dup 2)
4635 (minus:SI
4636 (minus:SI (const_int 0) (match_dup 3))
4637 (ltu:SI (reg:CC_C CC_REGNUM)
4638 (const_int 0))))])]
4639 {
4640 operands[2] = gen_highpart (SImode, operands[0]);
4641 operands[0] = gen_lowpart (SImode, operands[0]);
4642 operands[3] = gen_highpart (SImode, operands[1]);
4643 operands[1] = gen_lowpart (SImode, operands[1]);
4644 }
4645 [(set_attr "conds" "set")
4646 (set_attr "length" "8")
4647 (set_attr "type" "multiple")]
4648 )
4649
4650 (define_expand "negdi2"
4651 [(parallel
4652 [(set (match_operand:DI 0 "s_register_operand" "")
4653 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
4654 (clobber (reg:CC CC_REGNUM))])]
4655 "TARGET_EITHER"
4656 {
4657 if (TARGET_NEON)
4658 {
4659 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4660 DONE;
4661 }
4662 }
4663 )
4664
4665 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
4666 ;; The first alternative allows the common case of a *full* overlap.
4667 (define_insn_and_split "*negdi2_insn"
4668 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4669 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
4670 (clobber (reg:CC CC_REGNUM))]
4671 "TARGET_32BIT"
4672 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4673 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
4674 "&& reload_completed"
4675 [(parallel [(set (reg:CC CC_REGNUM)
4676 (compare:CC (const_int 0) (match_dup 1)))
4677 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4678 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4679 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4680 {
4681 operands[2] = gen_highpart (SImode, operands[0]);
4682 operands[0] = gen_lowpart (SImode, operands[0]);
4683 operands[3] = gen_highpart (SImode, operands[1]);
4684 operands[1] = gen_lowpart (SImode, operands[1]);
4685 }
4686 [(set_attr "conds" "clob")
4687 (set_attr "length" "8")
4688 (set_attr "type" "multiple")]
4689 )
4690
4691 (define_insn "*negsi2_carryin_compare"
4692 [(set (reg:CC CC_REGNUM)
4693 (compare:CC (const_int 0)
4694 (match_operand:SI 1 "s_register_operand" "r")))
4695 (set (match_operand:SI 0 "s_register_operand" "=r")
4696 (minus:SI (minus:SI (const_int 0)
4697 (match_dup 1))
4698 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4699 "TARGET_ARM"
4700 "rscs\\t%0, %1, #0"
4701 [(set_attr "conds" "set")
4702 (set_attr "type" "alus_imm")]
4703 )
4704
4705 (define_expand "negsi2"
4706 [(set (match_operand:SI 0 "s_register_operand" "")
4707 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4708 "TARGET_EITHER"
4709 ""
4710 )
4711
4712 (define_insn "*arm_negsi2"
4713 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4714 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
4715 "TARGET_32BIT"
4716 "rsb%?\\t%0, %1, #0"
4717 [(set_attr "predicable" "yes")
4718 (set_attr "predicable_short_it" "yes,no")
4719 (set_attr "arch" "t2,*")
4720 (set_attr "length" "4")
4721 (set_attr "type" "alu_sreg")]
4722 )
4723
4724 (define_expand "negsf2"
4725 [(set (match_operand:SF 0 "s_register_operand" "")
4726 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
4727 "TARGET_32BIT && TARGET_HARD_FLOAT"
4728 ""
4729 )
4730
4731 (define_expand "negdf2"
4732 [(set (match_operand:DF 0 "s_register_operand" "")
4733 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
4734 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
4735 "")
4736
4737 (define_insn_and_split "*zextendsidi_negsi"
4738 [(set (match_operand:DI 0 "s_register_operand" "=r")
4739 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4740 "TARGET_32BIT"
4741 "#"
4742 ""
4743 [(set (match_dup 2)
4744 (neg:SI (match_dup 1)))
4745 (set (match_dup 3)
4746 (const_int 0))]
4747 {
4748 operands[2] = gen_lowpart (SImode, operands[0]);
4749 operands[3] = gen_highpart (SImode, operands[0]);
4750 }
4751 [(set_attr "length" "8")
4752 (set_attr "type" "multiple")]
4753 )
4754
4755 ;; Negate an extended 32-bit value.
4756 (define_insn_and_split "*negdi_extendsidi"
4757 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4758 (neg:DI (sign_extend:DI
4759 (match_operand:SI 1 "s_register_operand" "l,r"))))
4760 (clobber (reg:CC CC_REGNUM))]
4761 "TARGET_32BIT"
4762 "#"
4763 "&& reload_completed"
4764 [(const_int 0)]
4765 {
4766 rtx low = gen_lowpart (SImode, operands[0]);
4767 rtx high = gen_highpart (SImode, operands[0]);
4768
4769 if (reg_overlap_mentioned_p (low, operands[1]))
4770 {
4771 /* Input overlaps the low word of the output. Use:
4772 asr Rhi, Rin, #31
4773 rsbs Rlo, Rin, #0
4774 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4775 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4776
4777 emit_insn (gen_rtx_SET (high,
4778 gen_rtx_ASHIFTRT (SImode, operands[1],
4779 GEN_INT (31))));
4780
4781 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4782 if (TARGET_ARM)
4783 emit_insn (gen_rtx_SET (high,
4784 gen_rtx_MINUS (SImode,
4785 gen_rtx_MINUS (SImode,
4786 const0_rtx,
4787 high),
4788 gen_rtx_LTU (SImode,
4789 cc_reg,
4790 const0_rtx))));
4791 else
4792 {
4793 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4794 emit_insn (gen_rtx_SET (high,
4795 gen_rtx_MINUS (SImode,
4796 gen_rtx_MINUS (SImode,
4797 high,
4798 two_x),
4799 gen_rtx_LTU (SImode,
4800 cc_reg,
4801 const0_rtx))));
4802 }
4803 }
4804 else
4805 {
4806 /* No overlap, or overlap on high word. Use:
4807 rsb Rlo, Rin, #0
4808 bic Rhi, Rlo, Rin
4809 asr Rhi, Rhi, #31
4810 Flags not needed for this sequence. */
4811 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4812 emit_insn (gen_rtx_SET (high,
4813 gen_rtx_AND (SImode,
4814 gen_rtx_NOT (SImode, operands[1]),
4815 low)));
4816 emit_insn (gen_rtx_SET (high,
4817 gen_rtx_ASHIFTRT (SImode, high,
4818 GEN_INT (31))));
4819 }
4820 DONE;
4821 }
4822 [(set_attr "length" "12")
4823 (set_attr "arch" "t2,*")
4824 (set_attr "type" "multiple")]
4825 )
4826
4827 (define_insn_and_split "*negdi_zero_extendsidi"
4828 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4829 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4830 (clobber (reg:CC CC_REGNUM))]
4831 "TARGET_32BIT"
4832 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4833 ;; Don't care what register is input to sbc,
4834 ;; since we just need to propagate the carry.
4835 "&& reload_completed"
4836 [(parallel [(set (reg:CC CC_REGNUM)
4837 (compare:CC (const_int 0) (match_dup 1)))
4838 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4839 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4840 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4841 {
4842 operands[2] = gen_highpart (SImode, operands[0]);
4843 operands[0] = gen_lowpart (SImode, operands[0]);
4844 }
4845 [(set_attr "conds" "clob")
4846 (set_attr "length" "8")
4847 (set_attr "type" "multiple")] ;; length in thumb is 4
4848 )
4849
4850 ;; abssi2 doesn't really clobber the condition codes if a different register
4851 ;; is being set. To keep things simple, assume during rtl manipulations that
4852 ;; it does, but tell the final scan operator the truth. Similarly for
4853 ;; (neg (abs...))
4854
4855 (define_expand "abssi2"
4856 [(parallel
4857 [(set (match_operand:SI 0 "s_register_operand" "")
4858 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
4859 (clobber (match_dup 2))])]
4860 "TARGET_EITHER"
4861 "
4862 if (TARGET_THUMB1)
4863 operands[2] = gen_rtx_SCRATCH (SImode);
4864 else
4865 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4866 ")
4867
4868 (define_insn_and_split "*arm_abssi2"
4869 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4870 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
4871 (clobber (reg:CC CC_REGNUM))]
4872 "TARGET_ARM"
4873 "#"
4874 "&& reload_completed"
4875 [(const_int 0)]
4876 {
4877 /* if (which_alternative == 0) */
4878 if (REGNO(operands[0]) == REGNO(operands[1]))
4879 {
4880 /* Emit the pattern:
4881 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4882 [(set (reg:CC CC_REGNUM)
4883 (compare:CC (match_dup 0) (const_int 0)))
4884 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4885 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4886 */
4887 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4888 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4889 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4890 (gen_rtx_LT (SImode,
4891 gen_rtx_REG (CCmode, CC_REGNUM),
4892 const0_rtx)),
4893 (gen_rtx_SET (operands[0],
4894 (gen_rtx_MINUS (SImode,
4895 const0_rtx,
4896 operands[1]))))));
4897 DONE;
4898 }
4899 else
4900 {
4901 /* Emit the pattern:
4902 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4903 [(set (match_dup 0)
4904 (xor:SI (match_dup 1)
4905 (ashiftrt:SI (match_dup 1) (const_int 31))))
4906 (set (match_dup 0)
4907 (minus:SI (match_dup 0)
4908 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4909 */
4910 emit_insn (gen_rtx_SET (operands[0],
4911 gen_rtx_XOR (SImode,
4912 gen_rtx_ASHIFTRT (SImode,
4913 operands[1],
4914 GEN_INT (31)),
4915 operands[1])));
4916 emit_insn (gen_rtx_SET (operands[0],
4917 gen_rtx_MINUS (SImode,
4918 operands[0],
4919 gen_rtx_ASHIFTRT (SImode,
4920 operands[1],
4921 GEN_INT (31)))));
4922 DONE;
4923 }
4924 }
4925 [(set_attr "conds" "clob,*")
4926 (set_attr "shift" "1")
4927 (set_attr "predicable" "no, yes")
4928 (set_attr "length" "8")
4929 (set_attr "type" "multiple")]
4930 )
4931
4932 (define_insn_and_split "*arm_neg_abssi2"
4933 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4934 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
4935 (clobber (reg:CC CC_REGNUM))]
4936 "TARGET_ARM"
4937 "#"
4938 "&& reload_completed"
4939 [(const_int 0)]
4940 {
4941 /* if (which_alternative == 0) */
4942 if (REGNO (operands[0]) == REGNO (operands[1]))
4943 {
4944 /* Emit the pattern:
4945 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4946 */
4947 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4948 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4949 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4950 gen_rtx_GT (SImode,
4951 gen_rtx_REG (CCmode, CC_REGNUM),
4952 const0_rtx),
4953 gen_rtx_SET (operands[0],
4954 (gen_rtx_MINUS (SImode,
4955 const0_rtx,
4956 operands[1])))));
4957 }
4958 else
4959 {
4960 /* Emit the pattern:
4961 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4962 */
4963 emit_insn (gen_rtx_SET (operands[0],
4964 gen_rtx_XOR (SImode,
4965 gen_rtx_ASHIFTRT (SImode,
4966 operands[1],
4967 GEN_INT (31)),
4968 operands[1])));
4969 emit_insn (gen_rtx_SET (operands[0],
4970 gen_rtx_MINUS (SImode,
4971 gen_rtx_ASHIFTRT (SImode,
4972 operands[1],
4973 GEN_INT (31)),
4974 operands[0])));
4975 }
4976 DONE;
4977 }
4978 [(set_attr "conds" "clob,*")
4979 (set_attr "shift" "1")
4980 (set_attr "predicable" "no, yes")
4981 (set_attr "length" "8")
4982 (set_attr "type" "multiple")]
4983 )
4984
4985 (define_expand "abssf2"
4986 [(set (match_operand:SF 0 "s_register_operand" "")
4987 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
4988 "TARGET_32BIT && TARGET_HARD_FLOAT"
4989 "")
4990
4991 (define_expand "absdf2"
4992 [(set (match_operand:DF 0 "s_register_operand" "")
4993 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
4994 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4995 "")
4996
4997 (define_expand "sqrtsf2"
4998 [(set (match_operand:SF 0 "s_register_operand" "")
4999 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
5000 "TARGET_32BIT && TARGET_HARD_FLOAT"
5001 "")
5002
5003 (define_expand "sqrtdf2"
5004 [(set (match_operand:DF 0 "s_register_operand" "")
5005 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
5006 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
5007 "")
5008
5009 (define_expand "one_cmpldi2"
5010 [(set (match_operand:DI 0 "s_register_operand" "")
5011 (not:DI (match_operand:DI 1 "s_register_operand" "")))]
5012 "TARGET_32BIT"
5013 "
5014 if (!TARGET_NEON && !TARGET_IWMMXT)
5015 {
5016 rtx low = simplify_gen_unary (NOT, SImode,
5017 gen_lowpart (SImode, operands[1]),
5018 SImode);
5019 rtx high = simplify_gen_unary (NOT, SImode,
5020 gen_highpart_mode (SImode, DImode,
5021 operands[1]),
5022 SImode);
5023
5024 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
5025 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
5026
5027 DONE;
5028 }
5029 /* Otherwise expand pattern as above. */
5030 "
5031 )
5032
5033 (define_insn_and_split "*one_cmpldi2_insn"
5034 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5035 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
5036 "TARGET_32BIT"
5037 "@
5038 vmvn\t%P0, %P1
5039 #
5040 #
5041 vmvn\t%P0, %P1"
5042 "TARGET_32BIT && reload_completed
5043 && arm_general_register_operand (operands[0], DImode)"
5044 [(set (match_dup 0) (not:SI (match_dup 1)))
5045 (set (match_dup 2) (not:SI (match_dup 3)))]
5046 "
5047 {
5048 operands[2] = gen_highpart (SImode, operands[0]);
5049 operands[0] = gen_lowpart (SImode, operands[0]);
5050 operands[3] = gen_highpart (SImode, operands[1]);
5051 operands[1] = gen_lowpart (SImode, operands[1]);
5052 }"
5053 [(set_attr "length" "*,8,8,*")
5054 (set_attr "predicable" "no,yes,yes,no")
5055 (set_attr "type" "neon_move,multiple,multiple,neon_move")
5056 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
5057 )
5058
5059 (define_expand "one_cmplsi2"
5060 [(set (match_operand:SI 0 "s_register_operand" "")
5061 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5062 "TARGET_EITHER"
5063 ""
5064 )
5065
5066 (define_insn "*arm_one_cmplsi2"
5067 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5068 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
5069 "TARGET_32BIT"
5070 "mvn%?\\t%0, %1"
5071 [(set_attr "predicable" "yes")
5072 (set_attr "predicable_short_it" "yes,no")
5073 (set_attr "arch" "t2,*")
5074 (set_attr "length" "4")
5075 (set_attr "type" "mvn_reg")]
5076 )
5077
5078 (define_insn "*notsi_compare0"
5079 [(set (reg:CC_NOOV CC_REGNUM)
5080 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5081 (const_int 0)))
5082 (set (match_operand:SI 0 "s_register_operand" "=r")
5083 (not:SI (match_dup 1)))]
5084 "TARGET_32BIT"
5085 "mvns%?\\t%0, %1"
5086 [(set_attr "conds" "set")
5087 (set_attr "type" "mvn_reg")]
5088 )
5089
5090 (define_insn "*notsi_compare0_scratch"
5091 [(set (reg:CC_NOOV CC_REGNUM)
5092 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5093 (const_int 0)))
5094 (clobber (match_scratch:SI 0 "=r"))]
5095 "TARGET_32BIT"
5096 "mvns%?\\t%0, %1"
5097 [(set_attr "conds" "set")
5098 (set_attr "type" "mvn_reg")]
5099 )
5100 \f
5101 ;; Fixed <--> Floating conversion insns
5102
5103 (define_expand "floatsihf2"
5104 [(set (match_operand:HF 0 "general_operand" "")
5105 (float:HF (match_operand:SI 1 "general_operand" "")))]
5106 "TARGET_EITHER"
5107 "
5108 {
5109 rtx op1 = gen_reg_rtx (SFmode);
5110 expand_float (op1, operands[1], 0);
5111 op1 = convert_to_mode (HFmode, op1, 0);
5112 emit_move_insn (operands[0], op1);
5113 DONE;
5114 }"
5115 )
5116
5117 (define_expand "floatdihf2"
5118 [(set (match_operand:HF 0 "general_operand" "")
5119 (float:HF (match_operand:DI 1 "general_operand" "")))]
5120 "TARGET_EITHER"
5121 "
5122 {
5123 rtx op1 = gen_reg_rtx (SFmode);
5124 expand_float (op1, operands[1], 0);
5125 op1 = convert_to_mode (HFmode, op1, 0);
5126 emit_move_insn (operands[0], op1);
5127 DONE;
5128 }"
5129 )
5130
5131 (define_expand "floatsisf2"
5132 [(set (match_operand:SF 0 "s_register_operand" "")
5133 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
5134 "TARGET_32BIT && TARGET_HARD_FLOAT"
5135 "
5136 ")
5137
5138 (define_expand "floatsidf2"
5139 [(set (match_operand:DF 0 "s_register_operand" "")
5140 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
5141 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5142 "
5143 ")
5144
5145 (define_expand "fix_trunchfsi2"
5146 [(set (match_operand:SI 0 "general_operand" "")
5147 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5148 "TARGET_EITHER"
5149 "
5150 {
5151 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5152 expand_fix (operands[0], op1, 0);
5153 DONE;
5154 }"
5155 )
5156
5157 (define_expand "fix_trunchfdi2"
5158 [(set (match_operand:DI 0 "general_operand" "")
5159 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5160 "TARGET_EITHER"
5161 "
5162 {
5163 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5164 expand_fix (operands[0], op1, 0);
5165 DONE;
5166 }"
5167 )
5168
5169 (define_expand "fix_truncsfsi2"
5170 [(set (match_operand:SI 0 "s_register_operand" "")
5171 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
5172 "TARGET_32BIT && TARGET_HARD_FLOAT"
5173 "
5174 ")
5175
5176 (define_expand "fix_truncdfsi2"
5177 [(set (match_operand:SI 0 "s_register_operand" "")
5178 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
5179 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5180 "
5181 ")
5182
5183 ;; Truncation insns
5184
5185 (define_expand "truncdfsf2"
5186 [(set (match_operand:SF 0 "s_register_operand" "")
5187 (float_truncate:SF
5188 (match_operand:DF 1 "s_register_operand" "")))]
5189 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5190 ""
5191 )
5192
5193 ;; DFmode to HFmode conversions on targets without a single-step hardware
5194 ;; instruction for it would have to go through SFmode. This is dangerous
5195 ;; as it introduces double rounding.
5196 ;;
5197 ;; Disable this pattern unless we are in an unsafe math mode, or we have
5198 ;; a single-step instruction.
5199
5200 (define_expand "truncdfhf2"
5201 [(set (match_operand:HF 0 "s_register_operand" "")
5202 (float_truncate:HF
5203 (match_operand:DF 1 "s_register_operand" "")))]
5204 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5205 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5206 {
5207 /* We don't have a direct instruction for this, so we must be in
5208 an unsafe math mode, and going via SFmode. */
5209
5210 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5211 {
5212 rtx op1;
5213 op1 = convert_to_mode (SFmode, operands[1], 0);
5214 op1 = convert_to_mode (HFmode, op1, 0);
5215 emit_move_insn (operands[0], op1);
5216 DONE;
5217 }
5218 /* Otherwise, we will pick this up as a single instruction with
5219 no intermediary rounding. */
5220 }
5221 )
5222 \f
5223 ;; Zero and sign extension instructions.
5224
5225 (define_insn "zero_extend<mode>di2"
5226 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
5227 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5228 "<qhs_zextenddi_cstr>")))]
5229 "TARGET_32BIT <qhs_zextenddi_cond>"
5230 "#"
5231 [(set_attr "length" "8,4,8,8")
5232 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
5233 (set_attr "ce_count" "2")
5234 (set_attr "predicable" "yes")
5235 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
5236 )
5237
5238 (define_insn "extend<mode>di2"
5239 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
5240 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5241 "<qhs_extenddi_cstr>")))]
5242 "TARGET_32BIT <qhs_sextenddi_cond>"
5243 "#"
5244 [(set_attr "length" "8,4,8,8,8")
5245 (set_attr "ce_count" "2")
5246 (set_attr "shift" "1")
5247 (set_attr "predicable" "yes")
5248 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5249 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
5250 )
5251
5252 ;; Splits for all extensions to DImode
5253 (define_split
5254 [(set (match_operand:DI 0 "s_register_operand" "")
5255 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
5256 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
5257 [(set (match_dup 0) (match_dup 1))]
5258 {
5259 rtx lo_part = gen_lowpart (SImode, operands[0]);
5260 machine_mode src_mode = GET_MODE (operands[1]);
5261
5262 if (REG_P (operands[0])
5263 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5264 emit_clobber (operands[0]);
5265 if (!REG_P (lo_part) || src_mode != SImode
5266 || !rtx_equal_p (lo_part, operands[1]))
5267 {
5268 if (src_mode == SImode)
5269 emit_move_insn (lo_part, operands[1]);
5270 else
5271 emit_insn (gen_rtx_SET (lo_part,
5272 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5273 operands[1] = lo_part;
5274 }
5275 operands[0] = gen_highpart (SImode, operands[0]);
5276 operands[1] = const0_rtx;
5277 })
5278
5279 (define_split
5280 [(set (match_operand:DI 0 "s_register_operand" "")
5281 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
5282 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
5283 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5284 {
5285 rtx lo_part = gen_lowpart (SImode, operands[0]);
5286 machine_mode src_mode = GET_MODE (operands[1]);
5287
5288 if (REG_P (operands[0])
5289 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5290 emit_clobber (operands[0]);
5291
5292 if (!REG_P (lo_part) || src_mode != SImode
5293 || !rtx_equal_p (lo_part, operands[1]))
5294 {
5295 if (src_mode == SImode)
5296 emit_move_insn (lo_part, operands[1]);
5297 else
5298 emit_insn (gen_rtx_SET (lo_part,
5299 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5300 operands[1] = lo_part;
5301 }
5302 operands[0] = gen_highpart (SImode, operands[0]);
5303 })
5304
5305 (define_expand "zero_extendhisi2"
5306 [(set (match_operand:SI 0 "s_register_operand" "")
5307 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
5308 "TARGET_EITHER"
5309 {
5310 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
5311 {
5312 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5313 DONE;
5314 }
5315 if (!arm_arch6 && !MEM_P (operands[1]))
5316 {
5317 rtx t = gen_lowpart (SImode, operands[1]);
5318 rtx tmp = gen_reg_rtx (SImode);
5319 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5320 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5321 DONE;
5322 }
5323 })
5324
5325 (define_split
5326 [(set (match_operand:SI 0 "s_register_operand" "")
5327 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
5328 "!TARGET_THUMB2 && !arm_arch6"
5329 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5330 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5331 {
5332 operands[2] = gen_lowpart (SImode, operands[1]);
5333 })
5334
5335 (define_insn "*arm_zero_extendhisi2"
5336 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5337 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5338 "TARGET_ARM && arm_arch4 && !arm_arch6"
5339 "@
5340 #
5341 ldrh%?\\t%0, %1"
5342 [(set_attr "type" "alu_shift_reg,load_byte")
5343 (set_attr "predicable" "yes")]
5344 )
5345
5346 (define_insn "*arm_zero_extendhisi2_v6"
5347 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5348 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
5349 "TARGET_ARM && arm_arch6"
5350 "@
5351 uxth%?\\t%0, %1
5352 ldrh%?\\t%0, %1"
5353 [(set_attr "predicable" "yes")
5354 (set_attr "type" "extend,load_byte")]
5355 )
5356
5357 (define_insn "*arm_zero_extendhisi2addsi"
5358 [(set (match_operand:SI 0 "s_register_operand" "=r")
5359 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5360 (match_operand:SI 2 "s_register_operand" "r")))]
5361 "TARGET_INT_SIMD"
5362 "uxtah%?\\t%0, %2, %1"
5363 [(set_attr "type" "alu_shift_reg")
5364 (set_attr "predicable" "yes")]
5365 )
5366
5367 (define_expand "zero_extendqisi2"
5368 [(set (match_operand:SI 0 "s_register_operand" "")
5369 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5370 "TARGET_EITHER"
5371 {
5372 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
5373 {
5374 emit_insn (gen_andsi3 (operands[0],
5375 gen_lowpart (SImode, operands[1]),
5376 GEN_INT (255)));
5377 DONE;
5378 }
5379 if (!arm_arch6 && !MEM_P (operands[1]))
5380 {
5381 rtx t = gen_lowpart (SImode, operands[1]);
5382 rtx tmp = gen_reg_rtx (SImode);
5383 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5384 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5385 DONE;
5386 }
5387 })
5388
5389 (define_split
5390 [(set (match_operand:SI 0 "s_register_operand" "")
5391 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
5392 "!arm_arch6"
5393 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5394 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5395 {
5396 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5397 if (TARGET_ARM)
5398 {
5399 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
5400 DONE;
5401 }
5402 })
5403
5404 (define_insn "*arm_zero_extendqisi2"
5405 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5406 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
5407 "TARGET_ARM && !arm_arch6"
5408 "@
5409 #
5410 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
5411 [(set_attr "length" "8,4")
5412 (set_attr "type" "alu_shift_reg,load_byte")
5413 (set_attr "predicable" "yes")]
5414 )
5415
5416 (define_insn "*arm_zero_extendqisi2_v6"
5417 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5418 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
5419 "TARGET_ARM && arm_arch6"
5420 "@
5421 uxtb%?\\t%0, %1
5422 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
5423 [(set_attr "type" "extend,load_byte")
5424 (set_attr "predicable" "yes")]
5425 )
5426
5427 (define_insn "*arm_zero_extendqisi2addsi"
5428 [(set (match_operand:SI 0 "s_register_operand" "=r")
5429 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5430 (match_operand:SI 2 "s_register_operand" "r")))]
5431 "TARGET_INT_SIMD"
5432 "uxtab%?\\t%0, %2, %1"
5433 [(set_attr "predicable" "yes")
5434 (set_attr "type" "alu_shift_reg")]
5435 )
5436
5437 (define_split
5438 [(set (match_operand:SI 0 "s_register_operand" "")
5439 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5440 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5441 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
5442 [(set (match_dup 2) (match_dup 1))
5443 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5444 ""
5445 )
5446
5447 (define_split
5448 [(set (match_operand:SI 0 "s_register_operand" "")
5449 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5450 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5451 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
5452 [(set (match_dup 2) (match_dup 1))
5453 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5454 ""
5455 )
5456
5457
5458 (define_split
5459 [(set (match_operand:SI 0 "s_register_operand" "")
5460 (IOR_XOR:SI (and:SI (ashift:SI
5461 (match_operand:SI 1 "s_register_operand" "")
5462 (match_operand:SI 2 "const_int_operand" ""))
5463 (match_operand:SI 3 "const_int_operand" ""))
5464 (zero_extend:SI
5465 (match_operator 5 "subreg_lowpart_operator"
5466 [(match_operand:SI 4 "s_register_operand" "")]))))]
5467 "TARGET_32BIT
5468 && (UINTVAL (operands[3])
5469 == (GET_MODE_MASK (GET_MODE (operands[5]))
5470 & (GET_MODE_MASK (GET_MODE (operands[5]))
5471 << (INTVAL (operands[2])))))"
5472 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
5473 (match_dup 4)))
5474 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5475 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5476 )
5477
5478 (define_insn "*compareqi_eq0"
5479 [(set (reg:CC_Z CC_REGNUM)
5480 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
5481 (const_int 0)))]
5482 "TARGET_32BIT"
5483 "tst%?\\t%0, #255"
5484 [(set_attr "conds" "set")
5485 (set_attr "predicable" "yes")
5486 (set_attr "type" "logic_imm")]
5487 )
5488
5489 (define_expand "extendhisi2"
5490 [(set (match_operand:SI 0 "s_register_operand" "")
5491 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
5492 "TARGET_EITHER"
5493 {
5494 if (TARGET_THUMB1)
5495 {
5496 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5497 DONE;
5498 }
5499 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5500 {
5501 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5502 DONE;
5503 }
5504
5505 if (!arm_arch6 && !MEM_P (operands[1]))
5506 {
5507 rtx t = gen_lowpart (SImode, operands[1]);
5508 rtx tmp = gen_reg_rtx (SImode);
5509 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5510 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5511 DONE;
5512 }
5513 })
5514
5515 (define_split
5516 [(parallel
5517 [(set (match_operand:SI 0 "register_operand" "")
5518 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5519 (clobber (match_scratch:SI 2 ""))])]
5520 "!arm_arch6"
5521 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5522 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5523 {
5524 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5525 })
5526
5527 ;; This pattern will only be used when ldsh is not available
5528 (define_expand "extendhisi2_mem"
5529 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5530 (set (match_dup 3)
5531 (zero_extend:SI (match_dup 7)))
5532 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5533 (set (match_operand:SI 0 "" "")
5534 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
5535 "TARGET_ARM"
5536 "
5537 {
5538 rtx mem1, mem2;
5539 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5540
5541 mem1 = change_address (operands[1], QImode, addr);
5542 mem2 = change_address (operands[1], QImode,
5543 plus_constant (Pmode, addr, 1));
5544 operands[0] = gen_lowpart (SImode, operands[0]);
5545 operands[1] = mem1;
5546 operands[2] = gen_reg_rtx (SImode);
5547 operands[3] = gen_reg_rtx (SImode);
5548 operands[6] = gen_reg_rtx (SImode);
5549 operands[7] = mem2;
5550
5551 if (BYTES_BIG_ENDIAN)
5552 {
5553 operands[4] = operands[2];
5554 operands[5] = operands[3];
5555 }
5556 else
5557 {
5558 operands[4] = operands[3];
5559 operands[5] = operands[2];
5560 }
5561 }"
5562 )
5563
5564 (define_split
5565 [(set (match_operand:SI 0 "register_operand" "")
5566 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5567 "!arm_arch6"
5568 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5569 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5570 {
5571 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5572 })
5573
5574 (define_insn "*arm_extendhisi2"
5575 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5576 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
5577 "TARGET_ARM && arm_arch4 && !arm_arch6"
5578 "@
5579 #
5580 ldrsh%?\\t%0, %1"
5581 [(set_attr "length" "8,4")
5582 (set_attr "type" "alu_shift_reg,load_byte")
5583 (set_attr "predicable" "yes")]
5584 )
5585
5586 ;; ??? Check Thumb-2 pool range
5587 (define_insn "*arm_extendhisi2_v6"
5588 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5589 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
5590 "TARGET_32BIT && arm_arch6"
5591 "@
5592 sxth%?\\t%0, %1
5593 ldrsh%?\\t%0, %1"
5594 [(set_attr "type" "extend,load_byte")
5595 (set_attr "predicable" "yes")]
5596 )
5597
5598 (define_insn "*arm_extendhisi2addsi"
5599 [(set (match_operand:SI 0 "s_register_operand" "=r")
5600 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5601 (match_operand:SI 2 "s_register_operand" "r")))]
5602 "TARGET_INT_SIMD"
5603 "sxtah%?\\t%0, %2, %1"
5604 [(set_attr "type" "alu_shift_reg")]
5605 )
5606
5607 (define_expand "extendqihi2"
5608 [(set (match_dup 2)
5609 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
5610 (const_int 24)))
5611 (set (match_operand:HI 0 "s_register_operand" "")
5612 (ashiftrt:SI (match_dup 2)
5613 (const_int 24)))]
5614 "TARGET_ARM"
5615 "
5616 {
5617 if (arm_arch4 && MEM_P (operands[1]))
5618 {
5619 emit_insn (gen_rtx_SET (operands[0],
5620 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5621 DONE;
5622 }
5623 if (!s_register_operand (operands[1], QImode))
5624 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5625 operands[0] = gen_lowpart (SImode, operands[0]);
5626 operands[1] = gen_lowpart (SImode, operands[1]);
5627 operands[2] = gen_reg_rtx (SImode);
5628 }"
5629 )
5630
5631 (define_insn "*arm_extendqihi_insn"
5632 [(set (match_operand:HI 0 "s_register_operand" "=r")
5633 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
5634 "TARGET_ARM && arm_arch4"
5635 "ldrsb%?\\t%0, %1"
5636 [(set_attr "type" "load_byte")
5637 (set_attr "predicable" "yes")]
5638 )
5639
5640 (define_expand "extendqisi2"
5641 [(set (match_operand:SI 0 "s_register_operand" "")
5642 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
5643 "TARGET_EITHER"
5644 {
5645 if (!arm_arch4 && MEM_P (operands[1]))
5646 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5647
5648 if (!arm_arch6 && !MEM_P (operands[1]))
5649 {
5650 rtx t = gen_lowpart (SImode, operands[1]);
5651 rtx tmp = gen_reg_rtx (SImode);
5652 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5653 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5654 DONE;
5655 }
5656 })
5657
5658 (define_split
5659 [(set (match_operand:SI 0 "register_operand" "")
5660 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5661 "!arm_arch6"
5662 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5663 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5664 {
5665 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5666 })
5667
5668 (define_insn "*arm_extendqisi"
5669 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5670 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5671 "TARGET_ARM && arm_arch4 && !arm_arch6"
5672 "@
5673 #
5674 ldrsb%?\\t%0, %1"
5675 [(set_attr "length" "8,4")
5676 (set_attr "type" "alu_shift_reg,load_byte")
5677 (set_attr "predicable" "yes")]
5678 )
5679
5680 (define_insn "*arm_extendqisi_v6"
5681 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5682 (sign_extend:SI
5683 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5684 "TARGET_ARM && arm_arch6"
5685 "@
5686 sxtb%?\\t%0, %1
5687 ldrsb%?\\t%0, %1"
5688 [(set_attr "type" "extend,load_byte")
5689 (set_attr "predicable" "yes")]
5690 )
5691
5692 (define_insn "*arm_extendqisi2addsi"
5693 [(set (match_operand:SI 0 "s_register_operand" "=r")
5694 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5695 (match_operand:SI 2 "s_register_operand" "r")))]
5696 "TARGET_INT_SIMD"
5697 "sxtab%?\\t%0, %2, %1"
5698 [(set_attr "type" "alu_shift_reg")
5699 (set_attr "predicable" "yes")]
5700 )
5701
5702 (define_expand "extendsfdf2"
5703 [(set (match_operand:DF 0 "s_register_operand" "")
5704 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
5705 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5706 ""
5707 )
5708
5709 ;; HFmode -> DFmode conversions where we don't have an instruction for it
5710 ;; must go through SFmode.
5711 ;;
5712 ;; This is always safe for an extend.
5713
5714 (define_expand "extendhfdf2"
5715 [(set (match_operand:DF 0 "s_register_operand" "")
5716 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
5717 "TARGET_EITHER"
5718 {
5719 /* We don't have a direct instruction for this, so go via SFmode. */
5720 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5721 {
5722 rtx op1;
5723 op1 = convert_to_mode (SFmode, operands[1], 0);
5724 op1 = convert_to_mode (DFmode, op1, 0);
5725 emit_insn (gen_movdf (operands[0], op1));
5726 DONE;
5727 }
5728 /* Otherwise, we're done producing RTL and will pick up the correct
5729 pattern to do this with one rounding-step in a single instruction. */
5730 }
5731 )
5732 \f
5733 ;; Move insns (including loads and stores)
5734
5735 ;; XXX Just some ideas about movti.
5736 ;; I don't think these are a good idea on the arm, there just aren't enough
5737 ;; registers
5738 ;;(define_expand "loadti"
5739 ;; [(set (match_operand:TI 0 "s_register_operand" "")
5740 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5741 ;; "" "")
5742
5743 ;;(define_expand "storeti"
5744 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
5745 ;; (match_operand:TI 1 "s_register_operand" ""))]
5746 ;; "" "")
5747
5748 ;;(define_expand "movti"
5749 ;; [(set (match_operand:TI 0 "general_operand" "")
5750 ;; (match_operand:TI 1 "general_operand" ""))]
5751 ;; ""
5752 ;; "
5753 ;;{
5754 ;; rtx insn;
5755 ;;
5756 ;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
5757 ;; operands[1] = copy_to_reg (operands[1]);
5758 ;; if (MEM_P (operands[0]))
5759 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5760 ;; else if (MEM_P (operands[1]))
5761 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5762 ;; else
5763 ;; FAIL;
5764 ;;
5765 ;; emit_insn (insn);
5766 ;; DONE;
5767 ;;}")
5768
5769 ;; Recognize garbage generated above.
5770
5771 ;;(define_insn ""
5772 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5773 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5774 ;; ""
5775 ;; "*
5776 ;; {
5777 ;; register mem = (which_alternative < 3);
5778 ;; register const char *template;
5779 ;;
5780 ;; operands[mem] = XEXP (operands[mem], 0);
5781 ;; switch (which_alternative)
5782 ;; {
5783 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5784 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5785 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5786 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5787 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5788 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
5789 ;; }
5790 ;; output_asm_insn (template, operands);
5791 ;; return \"\";
5792 ;; }")
5793
5794 (define_expand "movdi"
5795 [(set (match_operand:DI 0 "general_operand" "")
5796 (match_operand:DI 1 "general_operand" ""))]
5797 "TARGET_EITHER"
5798 "
5799 if (can_create_pseudo_p ())
5800 {
5801 if (!REG_P (operands[0]))
5802 operands[1] = force_reg (DImode, operands[1]);
5803 }
5804 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
5805 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
5806 {
5807 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5808 when expanding function calls. */
5809 gcc_assert (can_create_pseudo_p ());
5810 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5811 {
5812 /* Perform load into legal reg pair first, then move. */
5813 rtx reg = gen_reg_rtx (DImode);
5814 emit_insn (gen_movdi (reg, operands[1]));
5815 operands[1] = reg;
5816 }
5817 emit_move_insn (gen_lowpart (SImode, operands[0]),
5818 gen_lowpart (SImode, operands[1]));
5819 emit_move_insn (gen_highpart (SImode, operands[0]),
5820 gen_highpart (SImode, operands[1]));
5821 DONE;
5822 }
5823 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
5824 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
5825 {
5826 /* Avoid STRD's from an odd-numbered register pair in ARM state
5827 when expanding function prologue. */
5828 gcc_assert (can_create_pseudo_p ());
5829 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5830 ? gen_reg_rtx (DImode)
5831 : operands[0];
5832 emit_move_insn (gen_lowpart (SImode, split_dest),
5833 gen_lowpart (SImode, operands[1]));
5834 emit_move_insn (gen_highpart (SImode, split_dest),
5835 gen_highpart (SImode, operands[1]));
5836 if (split_dest != operands[0])
5837 emit_insn (gen_movdi (operands[0], split_dest));
5838 DONE;
5839 }
5840 "
5841 )
5842
5843 (define_insn "*arm_movdi"
5844 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5845 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
5846 "TARGET_32BIT
5847 && !(TARGET_HARD_FLOAT)
5848 && !TARGET_IWMMXT
5849 && ( register_operand (operands[0], DImode)
5850 || register_operand (operands[1], DImode))"
5851 "*
5852 switch (which_alternative)
5853 {
5854 case 0:
5855 case 1:
5856 case 2:
5857 return \"#\";
5858 case 3:
5859 /* Cannot load it directly, split to load it via MOV / MOVT. */
5860 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5861 return \"#\";
5862 /* Fall through. */
5863 default:
5864 return output_move_double (operands, true, NULL);
5865 }
5866 "
5867 [(set_attr "length" "8,12,16,8,8")
5868 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
5869 (set_attr "arm_pool_range" "*,*,*,1020,*")
5870 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5871 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
5872 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5873 )
5874
5875 (define_split
5876 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5877 (match_operand:ANY64 1 "immediate_operand" ""))]
5878 "TARGET_32BIT
5879 && reload_completed
5880 && (arm_disable_literal_pool
5881 || (arm_const_double_inline_cost (operands[1])
5882 <= arm_max_const_double_inline_cost ()))"
5883 [(const_int 0)]
5884 "
5885 arm_split_constant (SET, SImode, curr_insn,
5886 INTVAL (gen_lowpart (SImode, operands[1])),
5887 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5888 arm_split_constant (SET, SImode, curr_insn,
5889 INTVAL (gen_highpart_mode (SImode,
5890 GET_MODE (operands[0]),
5891 operands[1])),
5892 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5893 DONE;
5894 "
5895 )
5896
5897 ; If optimizing for size, or if we have load delay slots, then
5898 ; we want to split the constant into two separate operations.
5899 ; In both cases this may split a trivial part into a single data op
5900 ; leaving a single complex constant to load. We can also get longer
5901 ; offsets in a LDR which means we get better chances of sharing the pool
5902 ; entries. Finally, we can normally do a better job of scheduling
5903 ; LDR instructions than we can with LDM.
5904 ; This pattern will only match if the one above did not.
5905 (define_split
5906 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5907 (match_operand:ANY64 1 "const_double_operand" ""))]
5908 "TARGET_ARM && reload_completed
5909 && arm_const_double_by_parts (operands[1])"
5910 [(set (match_dup 0) (match_dup 1))
5911 (set (match_dup 2) (match_dup 3))]
5912 "
5913 operands[2] = gen_highpart (SImode, operands[0]);
5914 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5915 operands[1]);
5916 operands[0] = gen_lowpart (SImode, operands[0]);
5917 operands[1] = gen_lowpart (SImode, operands[1]);
5918 "
5919 )
5920
5921 (define_split
5922 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5923 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5924 "TARGET_EITHER && reload_completed"
5925 [(set (match_dup 0) (match_dup 1))
5926 (set (match_dup 2) (match_dup 3))]
5927 "
5928 operands[2] = gen_highpart (SImode, operands[0]);
5929 operands[3] = gen_highpart (SImode, operands[1]);
5930 operands[0] = gen_lowpart (SImode, operands[0]);
5931 operands[1] = gen_lowpart (SImode, operands[1]);
5932
5933 /* Handle a partial overlap. */
5934 if (rtx_equal_p (operands[0], operands[3]))
5935 {
5936 rtx tmp0 = operands[0];
5937 rtx tmp1 = operands[1];
5938
5939 operands[0] = operands[2];
5940 operands[1] = operands[3];
5941 operands[2] = tmp0;
5942 operands[3] = tmp1;
5943 }
5944 "
5945 )
5946
5947 ;; We can't actually do base+index doubleword loads if the index and
5948 ;; destination overlap. Split here so that we at least have chance to
5949 ;; schedule.
5950 (define_split
5951 [(set (match_operand:DI 0 "s_register_operand" "")
5952 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5953 (match_operand:SI 2 "s_register_operand" ""))))]
5954 "TARGET_LDRD
5955 && reg_overlap_mentioned_p (operands[0], operands[1])
5956 && reg_overlap_mentioned_p (operands[0], operands[2])"
5957 [(set (match_dup 4)
5958 (plus:SI (match_dup 1)
5959 (match_dup 2)))
5960 (set (match_dup 0)
5961 (mem:DI (match_dup 4)))]
5962 "
5963 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5964 "
5965 )
5966
5967 (define_expand "movsi"
5968 [(set (match_operand:SI 0 "general_operand" "")
5969 (match_operand:SI 1 "general_operand" ""))]
5970 "TARGET_EITHER"
5971 "
5972 {
5973 rtx base, offset, tmp;
5974
5975 if (TARGET_32BIT || TARGET_HAVE_MOVT)
5976 {
5977 /* Everything except mem = const or mem = mem can be done easily. */
5978 if (MEM_P (operands[0]))
5979 operands[1] = force_reg (SImode, operands[1]);
5980 if (arm_general_register_operand (operands[0], SImode)
5981 && CONST_INT_P (operands[1])
5982 && !(const_ok_for_arm (INTVAL (operands[1]))
5983 || const_ok_for_arm (~INTVAL (operands[1]))))
5984 {
5985 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5986 {
5987 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5988 DONE;
5989 }
5990 else
5991 {
5992 arm_split_constant (SET, SImode, NULL_RTX,
5993 INTVAL (operands[1]), operands[0], NULL_RTX,
5994 optimize && can_create_pseudo_p ());
5995 DONE;
5996 }
5997 }
5998 }
5999 else /* Target doesn't have MOVT... */
6000 {
6001 if (can_create_pseudo_p ())
6002 {
6003 if (!REG_P (operands[0]))
6004 operands[1] = force_reg (SImode, operands[1]);
6005 }
6006 }
6007
6008 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6009 {
6010 split_const (operands[1], &base, &offset);
6011 if (GET_CODE (base) == SYMBOL_REF
6012 && !offset_within_block_p (base, INTVAL (offset)))
6013 {
6014 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6015 emit_move_insn (tmp, base);
6016 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6017 DONE;
6018 }
6019 }
6020
6021 /* Recognize the case where operand[1] is a reference to thread-local
6022 data and load its address to a register. */
6023 if (arm_tls_referenced_p (operands[1]))
6024 {
6025 rtx tmp = operands[1];
6026 rtx addend = NULL;
6027
6028 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6029 {
6030 addend = XEXP (XEXP (tmp, 0), 1);
6031 tmp = XEXP (XEXP (tmp, 0), 0);
6032 }
6033
6034 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6035 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6036
6037 tmp = legitimize_tls_address (tmp,
6038 !can_create_pseudo_p () ? operands[0] : 0);
6039 if (addend)
6040 {
6041 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6042 tmp = force_operand (tmp, operands[0]);
6043 }
6044 operands[1] = tmp;
6045 }
6046 else if (flag_pic
6047 && (CONSTANT_P (operands[1])
6048 || symbol_mentioned_p (operands[1])
6049 || label_mentioned_p (operands[1])))
6050 operands[1] = legitimize_pic_address (operands[1], SImode,
6051 (!can_create_pseudo_p ()
6052 ? operands[0]
6053 : NULL_RTX), NULL_RTX,
6054 false /*compute_now*/);
6055 }
6056 "
6057 )
6058
6059 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6060 ;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6061 ;; so this does not matter.
6062 (define_insn "*arm_movt"
6063 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6064 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6065 (match_operand:SI 2 "general_operand" "i,i")))]
6066 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
6067 "@
6068 movt%?\t%0, #:upper16:%c2
6069 movt\t%0, #:upper16:%c2"
6070 [(set_attr "arch" "32,v8mb")
6071 (set_attr "predicable" "yes")
6072 (set_attr "length" "4")
6073 (set_attr "type" "alu_sreg")]
6074 )
6075
6076 (define_insn "*arm_movsi_insn"
6077 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
6078 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
6079 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
6080 && ( register_operand (operands[0], SImode)
6081 || register_operand (operands[1], SImode))"
6082 "@
6083 mov%?\\t%0, %1
6084 mov%?\\t%0, %1
6085 mvn%?\\t%0, #%B1
6086 movw%?\\t%0, %1
6087 ldr%?\\t%0, %1
6088 str%?\\t%1, %0"
6089 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
6090 (set_attr "predicable" "yes")
6091 (set_attr "arch" "*,*,*,v6t2,*,*")
6092 (set_attr "pool_range" "*,*,*,*,4096,*")
6093 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
6094 )
6095
6096 (define_split
6097 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6098 (match_operand:SI 1 "const_int_operand" ""))]
6099 "(TARGET_32BIT || TARGET_HAVE_MOVT)
6100 && (!(const_ok_for_arm (INTVAL (operands[1]))
6101 || const_ok_for_arm (~INTVAL (operands[1]))))"
6102 [(clobber (const_int 0))]
6103 "
6104 arm_split_constant (SET, SImode, NULL_RTX,
6105 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
6106 DONE;
6107 "
6108 )
6109
6110 ;; A normal way to do (symbol + offset) requires three instructions at least
6111 ;; (depends on how big the offset is) as below:
6112 ;; movw r0, #:lower16:g
6113 ;; movw r0, #:upper16:g
6114 ;; adds r0, #4
6115 ;;
6116 ;; A better way would be:
6117 ;; movw r0, #:lower16:g+4
6118 ;; movw r0, #:upper16:g+4
6119 ;;
6120 ;; The limitation of this way is that the length of offset should be a 16-bit
6121 ;; signed value, because current assembler only supports REL type relocation for
6122 ;; such case. If the more powerful RELA type is supported in future, we should
6123 ;; update this pattern to go with better way.
6124 (define_split
6125 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6126 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6127 (match_operand:SI 2 "const_int_operand" ""))))]
6128 "TARGET_THUMB
6129 && TARGET_HAVE_MOVT
6130 && arm_disable_literal_pool
6131 && reload_completed
6132 && GET_CODE (operands[1]) == SYMBOL_REF"
6133 [(clobber (const_int 0))]
6134 "
6135 int offset = INTVAL (operands[2]);
6136
6137 if (offset < -0x8000 || offset > 0x7fff)
6138 {
6139 arm_emit_movpair (operands[0], operands[1]);
6140 emit_insn (gen_rtx_SET (operands[0],
6141 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6142 }
6143 else
6144 {
6145 rtx op = gen_rtx_CONST (SImode,
6146 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6147 arm_emit_movpair (operands[0], op);
6148 }
6149 "
6150 )
6151
6152 ;; Split symbol_refs at the later stage (after cprop), instead of generating
6153 ;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6154 ;; and lo_sum would be merged back into memory load at cprop. However,
6155 ;; if the default is to prefer movt/movw rather than a load from the constant
6156 ;; pool, the performance is better.
6157 (define_split
6158 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6159 (match_operand:SI 1 "general_operand" ""))]
6160 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
6161 && !target_word_relocations
6162 && !arm_tls_referenced_p (operands[1])"
6163 [(clobber (const_int 0))]
6164 {
6165 arm_emit_movpair (operands[0], operands[1]);
6166 DONE;
6167 })
6168
6169 ;; When generating pic, we need to load the symbol offset into a register.
6170 ;; So that the optimizer does not confuse this with a normal symbol load
6171 ;; we use an unspec. The offset will be loaded from a constant pool entry,
6172 ;; since that is the only type of relocation we can use.
6173
6174 ;; Wrap calculation of the whole PIC address in a single pattern for the
6175 ;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6176 ;; a PIC address involves two loads from memory, so we want to CSE it
6177 ;; as often as possible.
6178 ;; This pattern will be split into one of the pic_load_addr_* patterns
6179 ;; and a move after GCSE optimizations.
6180 ;;
6181 ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6182 (define_expand "calculate_pic_address"
6183 [(set (match_operand:SI 0 "register_operand" "")
6184 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6185 (unspec:SI [(match_operand:SI 2 "" "")]
6186 UNSPEC_PIC_SYM))))]
6187 "flag_pic"
6188 )
6189
6190 ;; Split calculate_pic_address into pic_load_addr_* and a move.
6191 (define_split
6192 [(set (match_operand:SI 0 "register_operand" "")
6193 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6194 (unspec:SI [(match_operand:SI 2 "" "")]
6195 UNSPEC_PIC_SYM))))]
6196 "flag_pic"
6197 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6198 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6199 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6200 )
6201
6202 ;; operand1 is the memory address to go into
6203 ;; pic_load_addr_32bit.
6204 ;; operand2 is the PIC label to be emitted
6205 ;; from pic_add_dot_plus_eight.
6206 ;; We do this to allow hoisting of the entire insn.
6207 (define_insn_and_split "pic_load_addr_unified"
6208 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6209 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6210 (match_operand:SI 2 "" "")]
6211 UNSPEC_PIC_UNIFIED))]
6212 "flag_pic"
6213 "#"
6214 "&& reload_completed"
6215 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6216 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6217 (match_dup 2)] UNSPEC_PIC_BASE))]
6218 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6219 [(set_attr "type" "load_4,load_4,load_4")
6220 (set_attr "pool_range" "4096,4094,1022")
6221 (set_attr "neg_pool_range" "4084,0,0")
6222 (set_attr "arch" "a,t2,t1")
6223 (set_attr "length" "8,6,4")]
6224 )
6225
6226 ;; The rather odd constraints on the following are to force reload to leave
6227 ;; the insn alone, and to force the minipool generation pass to then move
6228 ;; the GOT symbol to memory.
6229
6230 (define_insn "pic_load_addr_32bit"
6231 [(set (match_operand:SI 0 "s_register_operand" "=r")
6232 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
6233 "TARGET_32BIT && flag_pic"
6234 "ldr%?\\t%0, %1"
6235 [(set_attr "type" "load_4")
6236 (set (attr "pool_range")
6237 (if_then_else (eq_attr "is_thumb" "no")
6238 (const_int 4096)
6239 (const_int 4094)))
6240 (set (attr "neg_pool_range")
6241 (if_then_else (eq_attr "is_thumb" "no")
6242 (const_int 4084)
6243 (const_int 0)))]
6244 )
6245
6246 (define_insn "pic_load_addr_thumb1"
6247 [(set (match_operand:SI 0 "s_register_operand" "=l")
6248 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
6249 "TARGET_THUMB1 && flag_pic"
6250 "ldr\\t%0, %1"
6251 [(set_attr "type" "load_4")
6252 (set (attr "pool_range") (const_int 1018))]
6253 )
6254
6255 (define_insn "pic_add_dot_plus_four"
6256 [(set (match_operand:SI 0 "register_operand" "=r")
6257 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6258 (const_int 4)
6259 (match_operand 2 "" "")]
6260 UNSPEC_PIC_BASE))]
6261 "TARGET_THUMB"
6262 "*
6263 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6264 INTVAL (operands[2]));
6265 return \"add\\t%0, %|pc\";
6266 "
6267 [(set_attr "length" "2")
6268 (set_attr "type" "alu_sreg")]
6269 )
6270
6271 (define_insn "pic_add_dot_plus_eight"
6272 [(set (match_operand:SI 0 "register_operand" "=r")
6273 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6274 (const_int 8)
6275 (match_operand 2 "" "")]
6276 UNSPEC_PIC_BASE))]
6277 "TARGET_ARM"
6278 "*
6279 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6280 INTVAL (operands[2]));
6281 return \"add%?\\t%0, %|pc, %1\";
6282 "
6283 [(set_attr "predicable" "yes")
6284 (set_attr "type" "alu_sreg")]
6285 )
6286
6287 (define_insn "tls_load_dot_plus_eight"
6288 [(set (match_operand:SI 0 "register_operand" "=r")
6289 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6290 (const_int 8)
6291 (match_operand 2 "" "")]
6292 UNSPEC_PIC_BASE)))]
6293 "TARGET_ARM"
6294 "*
6295 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6296 INTVAL (operands[2]));
6297 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6298 "
6299 [(set_attr "predicable" "yes")
6300 (set_attr "type" "load_4")]
6301 )
6302
6303 ;; PIC references to local variables can generate pic_add_dot_plus_eight
6304 ;; followed by a load. These sequences can be crunched down to
6305 ;; tls_load_dot_plus_eight by a peephole.
6306
6307 (define_peephole2
6308 [(set (match_operand:SI 0 "register_operand" "")
6309 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6310 (const_int 8)
6311 (match_operand 1 "" "")]
6312 UNSPEC_PIC_BASE))
6313 (set (match_operand:SI 2 "arm_general_register_operand" "")
6314 (mem:SI (match_dup 0)))]
6315 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
6316 [(set (match_dup 2)
6317 (mem:SI (unspec:SI [(match_dup 3)
6318 (const_int 8)
6319 (match_dup 1)]
6320 UNSPEC_PIC_BASE)))]
6321 ""
6322 )
6323
6324 (define_insn "pic_offset_arm"
6325 [(set (match_operand:SI 0 "register_operand" "=r")
6326 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6327 (unspec:SI [(match_operand:SI 2 "" "X")]
6328 UNSPEC_PIC_OFFSET))))]
6329 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6330 "ldr%?\\t%0, [%1,%2]"
6331 [(set_attr "type" "load_4")]
6332 )
6333
6334 (define_expand "builtin_setjmp_receiver"
6335 [(label_ref (match_operand 0 "" ""))]
6336 "flag_pic"
6337 "
6338 {
6339 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6340 register. */
6341 if (arm_pic_register != INVALID_REGNUM)
6342 arm_load_pic_register (1UL << 3, NULL_RTX);
6343 DONE;
6344 }")
6345
6346 ;; If copying one reg to another we can set the condition codes according to
6347 ;; its value. Such a move is common after a return from subroutine and the
6348 ;; result is being tested against zero.
6349
6350 (define_insn "*movsi_compare0"
6351 [(set (reg:CC CC_REGNUM)
6352 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6353 (const_int 0)))
6354 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6355 (match_dup 1))]
6356 "TARGET_32BIT"
6357 "@
6358 cmp%?\\t%0, #0
6359 subs%?\\t%0, %1, #0"
6360 [(set_attr "conds" "set")
6361 (set_attr "type" "alus_imm,alus_imm")]
6362 )
6363
6364 ;; Subroutine to store a half word from a register into memory.
6365 ;; Operand 0 is the source register (HImode)
6366 ;; Operand 1 is the destination address in a register (SImode)
6367
6368 ;; In both this routine and the next, we must be careful not to spill
6369 ;; a memory address of reg+large_const into a separate PLUS insn, since this
6370 ;; can generate unrecognizable rtl.
6371
6372 (define_expand "storehi"
6373 [;; store the low byte
6374 (set (match_operand 1 "" "") (match_dup 3))
6375 ;; extract the high byte
6376 (set (match_dup 2)
6377 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
6378 ;; store the high byte
6379 (set (match_dup 4) (match_dup 5))]
6380 "TARGET_ARM"
6381 "
6382 {
6383 rtx op1 = operands[1];
6384 rtx addr = XEXP (op1, 0);
6385 enum rtx_code code = GET_CODE (addr);
6386
6387 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
6388 || code == MINUS)
6389 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
6390
6391 operands[4] = adjust_address (op1, QImode, 1);
6392 operands[1] = adjust_address (operands[1], QImode, 0);
6393 operands[3] = gen_lowpart (QImode, operands[0]);
6394 operands[0] = gen_lowpart (SImode, operands[0]);
6395 operands[2] = gen_reg_rtx (SImode);
6396 operands[5] = gen_lowpart (QImode, operands[2]);
6397 }"
6398 )
6399
6400 (define_expand "storehi_bigend"
6401 [(set (match_dup 4) (match_dup 3))
6402 (set (match_dup 2)
6403 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
6404 (set (match_operand 1 "" "") (match_dup 5))]
6405 "TARGET_ARM"
6406 "
6407 {
6408 rtx op1 = operands[1];
6409 rtx addr = XEXP (op1, 0);
6410 enum rtx_code code = GET_CODE (addr);
6411
6412 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
6413 || code == MINUS)
6414 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
6415
6416 operands[4] = adjust_address (op1, QImode, 1);
6417 operands[1] = adjust_address (operands[1], QImode, 0);
6418 operands[3] = gen_lowpart (QImode, operands[0]);
6419 operands[0] = gen_lowpart (SImode, operands[0]);
6420 operands[2] = gen_reg_rtx (SImode);
6421 operands[5] = gen_lowpart (QImode, operands[2]);
6422 }"
6423 )
6424
6425 ;; Subroutine to store a half word integer constant into memory.
6426 (define_expand "storeinthi"
6427 [(set (match_operand 0 "" "")
6428 (match_operand 1 "" ""))
6429 (set (match_dup 3) (match_dup 2))]
6430 "TARGET_ARM"
6431 "
6432 {
6433 HOST_WIDE_INT value = INTVAL (operands[1]);
6434 rtx addr = XEXP (operands[0], 0);
6435 rtx op0 = operands[0];
6436 enum rtx_code code = GET_CODE (addr);
6437
6438 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
6439 || code == MINUS)
6440 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
6441
6442 operands[1] = gen_reg_rtx (SImode);
6443 if (BYTES_BIG_ENDIAN)
6444 {
6445 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6446 if ((value & 255) == ((value >> 8) & 255))
6447 operands[2] = operands[1];
6448 else
6449 {
6450 operands[2] = gen_reg_rtx (SImode);
6451 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6452 }
6453 }
6454 else
6455 {
6456 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6457 if ((value & 255) == ((value >> 8) & 255))
6458 operands[2] = operands[1];
6459 else
6460 {
6461 operands[2] = gen_reg_rtx (SImode);
6462 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6463 }
6464 }
6465
6466 operands[3] = adjust_address (op0, QImode, 1);
6467 operands[0] = adjust_address (operands[0], QImode, 0);
6468 operands[2] = gen_lowpart (QImode, operands[2]);
6469 operands[1] = gen_lowpart (QImode, operands[1]);
6470 }"
6471 )
6472
6473 (define_expand "storehi_single_op"
6474 [(set (match_operand:HI 0 "memory_operand" "")
6475 (match_operand:HI 1 "general_operand" ""))]
6476 "TARGET_32BIT && arm_arch4"
6477 "
6478 if (!s_register_operand (operands[1], HImode))
6479 operands[1] = copy_to_mode_reg (HImode, operands[1]);
6480 "
6481 )
6482
6483 (define_expand "movhi"
6484 [(set (match_operand:HI 0 "general_operand" "")
6485 (match_operand:HI 1 "general_operand" ""))]
6486 "TARGET_EITHER"
6487 "
6488 if (TARGET_ARM)
6489 {
6490 if (can_create_pseudo_p ())
6491 {
6492 if (MEM_P (operands[0]))
6493 {
6494 if (arm_arch4)
6495 {
6496 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6497 DONE;
6498 }
6499 if (CONST_INT_P (operands[1]))
6500 emit_insn (gen_storeinthi (operands[0], operands[1]));
6501 else
6502 {
6503 if (MEM_P (operands[1]))
6504 operands[1] = force_reg (HImode, operands[1]);
6505 if (BYTES_BIG_ENDIAN)
6506 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6507 else
6508 emit_insn (gen_storehi (operands[1], operands[0]));
6509 }
6510 DONE;
6511 }
6512 /* Sign extend a constant, and keep it in an SImode reg. */
6513 else if (CONST_INT_P (operands[1]))
6514 {
6515 rtx reg = gen_reg_rtx (SImode);
6516 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6517
6518 /* If the constant is already valid, leave it alone. */
6519 if (!const_ok_for_arm (val))
6520 {
6521 /* If setting all the top bits will make the constant
6522 loadable in a single instruction, then set them.
6523 Otherwise, sign extend the number. */
6524
6525 if (const_ok_for_arm (~(val | ~0xffff)))
6526 val |= ~0xffff;
6527 else if (val & 0x8000)
6528 val |= ~0xffff;
6529 }
6530
6531 emit_insn (gen_movsi (reg, GEN_INT (val)));
6532 operands[1] = gen_lowpart (HImode, reg);
6533 }
6534 else if (arm_arch4 && optimize && can_create_pseudo_p ()
6535 && MEM_P (operands[1]))
6536 {
6537 rtx reg = gen_reg_rtx (SImode);
6538
6539 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6540 operands[1] = gen_lowpart (HImode, reg);
6541 }
6542 else if (!arm_arch4)
6543 {
6544 if (MEM_P (operands[1]))
6545 {
6546 rtx base;
6547 rtx offset = const0_rtx;
6548 rtx reg = gen_reg_rtx (SImode);
6549
6550 if ((REG_P (base = XEXP (operands[1], 0))
6551 || (GET_CODE (base) == PLUS
6552 && (CONST_INT_P (offset = XEXP (base, 1)))
6553 && ((INTVAL(offset) & 1) != 1)
6554 && REG_P (base = XEXP (base, 0))))
6555 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
6556 {
6557 rtx new_rtx;
6558
6559 new_rtx = widen_memory_access (operands[1], SImode,
6560 ((INTVAL (offset) & ~3)
6561 - INTVAL (offset)));
6562 emit_insn (gen_movsi (reg, new_rtx));
6563 if (((INTVAL (offset) & 2) != 0)
6564 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6565 {
6566 rtx reg2 = gen_reg_rtx (SImode);
6567
6568 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6569 reg = reg2;
6570 }
6571 }
6572 else
6573 emit_insn (gen_movhi_bytes (reg, operands[1]));
6574
6575 operands[1] = gen_lowpart (HImode, reg);
6576 }
6577 }
6578 }
6579 /* Handle loading a large integer during reload. */
6580 else if (CONST_INT_P (operands[1])
6581 && !const_ok_for_arm (INTVAL (operands[1]))
6582 && !const_ok_for_arm (~INTVAL (operands[1])))
6583 {
6584 /* Writing a constant to memory needs a scratch, which should
6585 be handled with SECONDARY_RELOADs. */
6586 gcc_assert (REG_P (operands[0]));
6587
6588 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6589 emit_insn (gen_movsi (operands[0], operands[1]));
6590 DONE;
6591 }
6592 }
6593 else if (TARGET_THUMB2)
6594 {
6595 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
6596 if (can_create_pseudo_p ())
6597 {
6598 if (!REG_P (operands[0]))
6599 operands[1] = force_reg (HImode, operands[1]);
6600 /* Zero extend a constant, and keep it in an SImode reg. */
6601 else if (CONST_INT_P (operands[1]))
6602 {
6603 rtx reg = gen_reg_rtx (SImode);
6604 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6605
6606 emit_insn (gen_movsi (reg, GEN_INT (val)));
6607 operands[1] = gen_lowpart (HImode, reg);
6608 }
6609 }
6610 }
6611 else /* TARGET_THUMB1 */
6612 {
6613 if (can_create_pseudo_p ())
6614 {
6615 if (CONST_INT_P (operands[1]))
6616 {
6617 rtx reg = gen_reg_rtx (SImode);
6618
6619 emit_insn (gen_movsi (reg, operands[1]));
6620 operands[1] = gen_lowpart (HImode, reg);
6621 }
6622
6623 /* ??? We shouldn't really get invalid addresses here, but this can
6624 happen if we are passed a SP (never OK for HImode/QImode) or
6625 virtual register (also rejected as illegitimate for HImode/QImode)
6626 relative address. */
6627 /* ??? This should perhaps be fixed elsewhere, for instance, in
6628 fixup_stack_1, by checking for other kinds of invalid addresses,
6629 e.g. a bare reference to a virtual register. This may confuse the
6630 alpha though, which must handle this case differently. */
6631 if (MEM_P (operands[0])
6632 && !memory_address_p (GET_MODE (operands[0]),
6633 XEXP (operands[0], 0)))
6634 operands[0]
6635 = replace_equiv_address (operands[0],
6636 copy_to_reg (XEXP (operands[0], 0)));
6637
6638 if (MEM_P (operands[1])
6639 && !memory_address_p (GET_MODE (operands[1]),
6640 XEXP (operands[1], 0)))
6641 operands[1]
6642 = replace_equiv_address (operands[1],
6643 copy_to_reg (XEXP (operands[1], 0)));
6644
6645 if (MEM_P (operands[1]) && optimize > 0)
6646 {
6647 rtx reg = gen_reg_rtx (SImode);
6648
6649 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6650 operands[1] = gen_lowpart (HImode, reg);
6651 }
6652
6653 if (MEM_P (operands[0]))
6654 operands[1] = force_reg (HImode, operands[1]);
6655 }
6656 else if (CONST_INT_P (operands[1])
6657 && !satisfies_constraint_I (operands[1]))
6658 {
6659 /* Handle loading a large integer during reload. */
6660
6661 /* Writing a constant to memory needs a scratch, which should
6662 be handled with SECONDARY_RELOADs. */
6663 gcc_assert (REG_P (operands[0]));
6664
6665 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6666 emit_insn (gen_movsi (operands[0], operands[1]));
6667 DONE;
6668 }
6669 }
6670 "
6671 )
6672
6673 (define_expand "movhi_bytes"
6674 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6675 (set (match_dup 3)
6676 (zero_extend:SI (match_dup 6)))
6677 (set (match_operand:SI 0 "" "")
6678 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6679 "TARGET_ARM"
6680 "
6681 {
6682 rtx mem1, mem2;
6683 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6684
6685 mem1 = change_address (operands[1], QImode, addr);
6686 mem2 = change_address (operands[1], QImode,
6687 plus_constant (Pmode, addr, 1));
6688 operands[0] = gen_lowpart (SImode, operands[0]);
6689 operands[1] = mem1;
6690 operands[2] = gen_reg_rtx (SImode);
6691 operands[3] = gen_reg_rtx (SImode);
6692 operands[6] = mem2;
6693
6694 if (BYTES_BIG_ENDIAN)
6695 {
6696 operands[4] = operands[2];
6697 operands[5] = operands[3];
6698 }
6699 else
6700 {
6701 operands[4] = operands[3];
6702 operands[5] = operands[2];
6703 }
6704 }"
6705 )
6706
6707 (define_expand "movhi_bigend"
6708 [(set (match_dup 2)
6709 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6710 (const_int 16)))
6711 (set (match_dup 3)
6712 (ashiftrt:SI (match_dup 2) (const_int 16)))
6713 (set (match_operand:HI 0 "s_register_operand" "")
6714 (match_dup 4))]
6715 "TARGET_ARM"
6716 "
6717 operands[2] = gen_reg_rtx (SImode);
6718 operands[3] = gen_reg_rtx (SImode);
6719 operands[4] = gen_lowpart (HImode, operands[3]);
6720 "
6721 )
6722
6723 ;; Pattern to recognize insn generated default case above
6724 (define_insn "*movhi_insn_arch4"
6725 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6726 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
6727 "TARGET_ARM
6728 && arm_arch4 && !TARGET_HARD_FLOAT
6729 && (register_operand (operands[0], HImode)
6730 || register_operand (operands[1], HImode))"
6731 "@
6732 mov%?\\t%0, %1\\t%@ movhi
6733 mvn%?\\t%0, #%B1\\t%@ movhi
6734 movw%?\\t%0, %L1\\t%@ movhi
6735 strh%?\\t%1, %0\\t%@ movhi
6736 ldrh%?\\t%0, %1\\t%@ movhi"
6737 [(set_attr "predicable" "yes")
6738 (set_attr "pool_range" "*,*,*,*,256")
6739 (set_attr "neg_pool_range" "*,*,*,*,244")
6740 (set_attr "arch" "*,*,v6t2,*,*")
6741 (set_attr_alternative "type"
6742 [(if_then_else (match_operand 1 "const_int_operand" "")
6743 (const_string "mov_imm" )
6744 (const_string "mov_reg"))
6745 (const_string "mvn_imm")
6746 (const_string "mov_imm")
6747 (const_string "store_4")
6748 (const_string "load_4")])]
6749 )
6750
6751 (define_insn "*movhi_bytes"
6752 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
6753 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
6754 "TARGET_ARM && !TARGET_HARD_FLOAT"
6755 "@
6756 mov%?\\t%0, %1\\t%@ movhi
6757 mov%?\\t%0, %1\\t%@ movhi
6758 mvn%?\\t%0, #%B1\\t%@ movhi"
6759 [(set_attr "predicable" "yes")
6760 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
6761 )
6762
6763 ;; We use a DImode scratch because we may occasionally need an additional
6764 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
6765 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
6766 (define_expand "reload_outhi"
6767 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6768 (match_operand:HI 1 "s_register_operand" "r")
6769 (match_operand:DI 2 "s_register_operand" "=&l")])]
6770 "TARGET_EITHER"
6771 "if (TARGET_ARM)
6772 arm_reload_out_hi (operands);
6773 else
6774 thumb_reload_out_hi (operands);
6775 DONE;
6776 "
6777 )
6778
6779 (define_expand "reload_inhi"
6780 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6781 (match_operand:HI 1 "arm_reload_memory_operand" "o")
6782 (match_operand:DI 2 "s_register_operand" "=&r")])]
6783 "TARGET_EITHER"
6784 "
6785 if (TARGET_ARM)
6786 arm_reload_in_hi (operands);
6787 else
6788 thumb_reload_out_hi (operands);
6789 DONE;
6790 ")
6791
6792 (define_expand "movqi"
6793 [(set (match_operand:QI 0 "general_operand" "")
6794 (match_operand:QI 1 "general_operand" ""))]
6795 "TARGET_EITHER"
6796 "
6797 /* Everything except mem = const or mem = mem can be done easily */
6798
6799 if (can_create_pseudo_p ())
6800 {
6801 if (CONST_INT_P (operands[1]))
6802 {
6803 rtx reg = gen_reg_rtx (SImode);
6804
6805 /* For thumb we want an unsigned immediate, then we are more likely
6806 to be able to use a movs insn. */
6807 if (TARGET_THUMB)
6808 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6809
6810 emit_insn (gen_movsi (reg, operands[1]));
6811 operands[1] = gen_lowpart (QImode, reg);
6812 }
6813
6814 if (TARGET_THUMB)
6815 {
6816 /* ??? We shouldn't really get invalid addresses here, but this can
6817 happen if we are passed a SP (never OK for HImode/QImode) or
6818 virtual register (also rejected as illegitimate for HImode/QImode)
6819 relative address. */
6820 /* ??? This should perhaps be fixed elsewhere, for instance, in
6821 fixup_stack_1, by checking for other kinds of invalid addresses,
6822 e.g. a bare reference to a virtual register. This may confuse the
6823 alpha though, which must handle this case differently. */
6824 if (MEM_P (operands[0])
6825 && !memory_address_p (GET_MODE (operands[0]),
6826 XEXP (operands[0], 0)))
6827 operands[0]
6828 = replace_equiv_address (operands[0],
6829 copy_to_reg (XEXP (operands[0], 0)));
6830 if (MEM_P (operands[1])
6831 && !memory_address_p (GET_MODE (operands[1]),
6832 XEXP (operands[1], 0)))
6833 operands[1]
6834 = replace_equiv_address (operands[1],
6835 copy_to_reg (XEXP (operands[1], 0)));
6836 }
6837
6838 if (MEM_P (operands[1]) && optimize > 0)
6839 {
6840 rtx reg = gen_reg_rtx (SImode);
6841
6842 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6843 operands[1] = gen_lowpart (QImode, reg);
6844 }
6845
6846 if (MEM_P (operands[0]))
6847 operands[1] = force_reg (QImode, operands[1]);
6848 }
6849 else if (TARGET_THUMB
6850 && CONST_INT_P (operands[1])
6851 && !satisfies_constraint_I (operands[1]))
6852 {
6853 /* Handle loading a large integer during reload. */
6854
6855 /* Writing a constant to memory needs a scratch, which should
6856 be handled with SECONDARY_RELOADs. */
6857 gcc_assert (REG_P (operands[0]));
6858
6859 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6860 emit_insn (gen_movsi (operands[0], operands[1]));
6861 DONE;
6862 }
6863 "
6864 )
6865
6866 (define_insn "*arm_movqi_insn"
6867 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
6868 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
6869 "TARGET_32BIT
6870 && ( register_operand (operands[0], QImode)
6871 || register_operand (operands[1], QImode))"
6872 "@
6873 mov%?\\t%0, %1
6874 mov%?\\t%0, %1
6875 mov%?\\t%0, %1
6876 mov%?\\t%0, %1
6877 mvn%?\\t%0, #%B1
6878 ldrb%?\\t%0, %1
6879 strb%?\\t%1, %0
6880 ldrb%?\\t%0, %1
6881 strb%?\\t%1, %0"
6882 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
6883 (set_attr "predicable" "yes")
6884 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
6885 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6886 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
6887 )
6888
6889 ;; HFmode moves
6890 (define_expand "movhf"
6891 [(set (match_operand:HF 0 "general_operand" "")
6892 (match_operand:HF 1 "general_operand" ""))]
6893 "TARGET_EITHER"
6894 "
6895 if (TARGET_32BIT)
6896 {
6897 if (MEM_P (operands[0]))
6898 operands[1] = force_reg (HFmode, operands[1]);
6899 }
6900 else /* TARGET_THUMB1 */
6901 {
6902 if (can_create_pseudo_p ())
6903 {
6904 if (!REG_P (operands[0]))
6905 operands[1] = force_reg (HFmode, operands[1]);
6906 }
6907 }
6908 "
6909 )
6910
6911 (define_insn "*arm32_movhf"
6912 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6913 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6914 "TARGET_32BIT && !TARGET_HARD_FLOAT
6915 && ( s_register_operand (operands[0], HFmode)
6916 || s_register_operand (operands[1], HFmode))"
6917 "*
6918 switch (which_alternative)
6919 {
6920 case 0: /* ARM register from memory */
6921 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
6922 case 1: /* memory from ARM register */
6923 return \"strh%?\\t%1, %0\\t%@ __fp16\";
6924 case 2: /* ARM register from ARM register */
6925 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6926 case 3: /* ARM register from constant */
6927 {
6928 long bits;
6929 rtx ops[4];
6930
6931 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6932 HFmode);
6933 ops[0] = operands[0];
6934 ops[1] = GEN_INT (bits);
6935 ops[2] = GEN_INT (bits & 0xff00);
6936 ops[3] = GEN_INT (bits & 0x00ff);
6937
6938 if (arm_arch_thumb2)
6939 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6940 else
6941 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6942 return \"\";
6943 }
6944 default:
6945 gcc_unreachable ();
6946 }
6947 "
6948 [(set_attr "conds" "unconditional")
6949 (set_attr "type" "load_4,store_4,mov_reg,multiple")
6950 (set_attr "length" "4,4,4,8")
6951 (set_attr "predicable" "yes")]
6952 )
6953
6954 (define_expand "movsf"
6955 [(set (match_operand:SF 0 "general_operand" "")
6956 (match_operand:SF 1 "general_operand" ""))]
6957 "TARGET_EITHER"
6958 "
6959 if (TARGET_32BIT)
6960 {
6961 if (MEM_P (operands[0]))
6962 operands[1] = force_reg (SFmode, operands[1]);
6963 }
6964 else /* TARGET_THUMB1 */
6965 {
6966 if (can_create_pseudo_p ())
6967 {
6968 if (!REG_P (operands[0]))
6969 operands[1] = force_reg (SFmode, operands[1]);
6970 }
6971 }
6972
6973 /* Cannot load it directly, generate a load with clobber so that it can be
6974 loaded via GPR with MOV / MOVT. */
6975 if (arm_disable_literal_pool
6976 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6977 && CONST_DOUBLE_P (operands[1])
6978 && TARGET_HARD_FLOAT
6979 && !vfp3_const_double_rtx (operands[1]))
6980 {
6981 rtx clobreg = gen_reg_rtx (SFmode);
6982 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6983 clobreg));
6984 DONE;
6985 }
6986 "
6987 )
6988
6989 ;; Transform a floating-point move of a constant into a core register into
6990 ;; an SImode operation.
6991 (define_split
6992 [(set (match_operand:SF 0 "arm_general_register_operand" "")
6993 (match_operand:SF 1 "immediate_operand" ""))]
6994 "TARGET_EITHER
6995 && reload_completed
6996 && CONST_DOUBLE_P (operands[1])"
6997 [(set (match_dup 2) (match_dup 3))]
6998 "
6999 operands[2] = gen_lowpart (SImode, operands[0]);
7000 operands[3] = gen_lowpart (SImode, operands[1]);
7001 if (operands[2] == 0 || operands[3] == 0)
7002 FAIL;
7003 "
7004 )
7005
7006 (define_insn "*arm_movsf_soft_insn"
7007 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
7008 (match_operand:SF 1 "general_operand" "r,mE,r"))]
7009 "TARGET_32BIT
7010 && TARGET_SOFT_FLOAT
7011 && (!MEM_P (operands[0])
7012 || register_operand (operands[1], SFmode))"
7013 {
7014 switch (which_alternative)
7015 {
7016 case 0: return \"mov%?\\t%0, %1\";
7017 case 1:
7018 /* Cannot load it directly, split to load it via MOV / MOVT. */
7019 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
7020 return \"#\";
7021 return \"ldr%?\\t%0, %1\\t%@ float\";
7022 case 2: return \"str%?\\t%1, %0\\t%@ float\";
7023 default: gcc_unreachable ();
7024 }
7025 }
7026 [(set_attr "predicable" "yes")
7027 (set_attr "type" "mov_reg,load_4,store_4")
7028 (set_attr "arm_pool_range" "*,4096,*")
7029 (set_attr "thumb2_pool_range" "*,4094,*")
7030 (set_attr "arm_neg_pool_range" "*,4084,*")
7031 (set_attr "thumb2_neg_pool_range" "*,0,*")]
7032 )
7033
7034 ;; Splitter for the above.
7035 (define_split
7036 [(set (match_operand:SF 0 "s_register_operand")
7037 (match_operand:SF 1 "const_double_operand"))]
7038 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
7039 [(const_int 0)]
7040 {
7041 long buf;
7042 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
7043 rtx cst = gen_int_mode (buf, SImode);
7044 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
7045 DONE;
7046 }
7047 )
7048
7049 (define_expand "movdf"
7050 [(set (match_operand:DF 0 "general_operand" "")
7051 (match_operand:DF 1 "general_operand" ""))]
7052 "TARGET_EITHER"
7053 "
7054 if (TARGET_32BIT)
7055 {
7056 if (MEM_P (operands[0]))
7057 operands[1] = force_reg (DFmode, operands[1]);
7058 }
7059 else /* TARGET_THUMB */
7060 {
7061 if (can_create_pseudo_p ())
7062 {
7063 if (!REG_P (operands[0]))
7064 operands[1] = force_reg (DFmode, operands[1]);
7065 }
7066 }
7067
7068 /* Cannot load it directly, generate a load with clobber so that it can be
7069 loaded via GPR with MOV / MOVT. */
7070 if (arm_disable_literal_pool
7071 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
7072 && CONSTANT_P (operands[1])
7073 && TARGET_HARD_FLOAT
7074 && !arm_const_double_rtx (operands[1])
7075 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
7076 {
7077 rtx clobreg = gen_reg_rtx (DFmode);
7078 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
7079 clobreg));
7080 DONE;
7081 }
7082 "
7083 )
7084
7085 ;; Reloading a df mode value stored in integer regs to memory can require a
7086 ;; scratch reg.
7087 (define_expand "reload_outdf"
7088 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
7089 (match_operand:DF 1 "s_register_operand" "r")
7090 (match_operand:SI 2 "s_register_operand" "=&r")]
7091 "TARGET_THUMB2"
7092 "
7093 {
7094 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
7095
7096 if (code == REG)
7097 operands[2] = XEXP (operands[0], 0);
7098 else if (code == POST_INC || code == PRE_DEC)
7099 {
7100 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7101 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7102 emit_insn (gen_movdi (operands[0], operands[1]));
7103 DONE;
7104 }
7105 else if (code == PRE_INC)
7106 {
7107 rtx reg = XEXP (XEXP (operands[0], 0), 0);
7108
7109 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7110 operands[2] = reg;
7111 }
7112 else if (code == POST_DEC)
7113 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7114 else
7115 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7116 XEXP (XEXP (operands[0], 0), 1)));
7117
7118 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
7119 operands[1]));
7120
7121 if (code == POST_DEC)
7122 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7123
7124 DONE;
7125 }"
7126 )
7127
7128 (define_insn "*movdf_soft_insn"
7129 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
7130 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
7131 "TARGET_32BIT && TARGET_SOFT_FLOAT
7132 && ( register_operand (operands[0], DFmode)
7133 || register_operand (operands[1], DFmode))"
7134 "*
7135 switch (which_alternative)
7136 {
7137 case 0:
7138 case 1:
7139 case 2:
7140 return \"#\";
7141 case 3:
7142 /* Cannot load it directly, split to load it via MOV / MOVT. */
7143 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
7144 return \"#\";
7145 /* Fall through. */
7146 default:
7147 return output_move_double (operands, true, NULL);
7148 }
7149 "
7150 [(set_attr "length" "8,12,16,8,8")
7151 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
7152 (set_attr "arm_pool_range" "*,*,*,1020,*")
7153 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
7154 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
7155 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
7156 )
7157
7158 ;; Splitter for the above.
7159 (define_split
7160 [(set (match_operand:DF 0 "s_register_operand")
7161 (match_operand:DF 1 "const_double_operand"))]
7162 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
7163 [(const_int 0)]
7164 {
7165 long buf[2];
7166 int order = BYTES_BIG_ENDIAN ? 1 : 0;
7167 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
7168 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
7169 ival |= (zext_hwi (buf[1 - order], 32) << 32);
7170 rtx cst = gen_int_mode (ival, DImode);
7171 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
7172 DONE;
7173 }
7174 )
7175 \f
7176
7177 ;; load- and store-multiple insns
7178 ;; The arm can load/store any set of registers, provided that they are in
7179 ;; ascending order, but these expanders assume a contiguous set.
7180
7181 (define_expand "load_multiple"
7182 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7183 (match_operand:SI 1 "" ""))
7184 (use (match_operand:SI 2 "" ""))])]
7185 "TARGET_32BIT"
7186 {
7187 HOST_WIDE_INT offset = 0;
7188
7189 /* Support only fixed point registers. */
7190 if (!CONST_INT_P (operands[2])
7191 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
7192 || INTVAL (operands[2]) < 2
7193 || !MEM_P (operands[1])
7194 || !REG_P (operands[0])
7195 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7196 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
7197 FAIL;
7198
7199 operands[3]
7200 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7201 INTVAL (operands[2]),
7202 force_reg (SImode, XEXP (operands[1], 0)),
7203 FALSE, operands[1], &offset);
7204 })
7205
7206 (define_expand "store_multiple"
7207 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7208 (match_operand:SI 1 "" ""))
7209 (use (match_operand:SI 2 "" ""))])]
7210 "TARGET_32BIT"
7211 {
7212 HOST_WIDE_INT offset = 0;
7213
7214 /* Support only fixed point registers. */
7215 if (!CONST_INT_P (operands[2])
7216 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
7217 || INTVAL (operands[2]) < 2
7218 || !REG_P (operands[1])
7219 || !MEM_P (operands[0])
7220 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7221 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
7222 FAIL;
7223
7224 operands[3]
7225 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7226 INTVAL (operands[2]),
7227 force_reg (SImode, XEXP (operands[0], 0)),
7228 FALSE, operands[0], &offset);
7229 })
7230
7231
7232 (define_expand "setmemsi"
7233 [(match_operand:BLK 0 "general_operand" "")
7234 (match_operand:SI 1 "const_int_operand" "")
7235 (match_operand:SI 2 "const_int_operand" "")
7236 (match_operand:SI 3 "const_int_operand" "")]
7237 "TARGET_32BIT"
7238 {
7239 if (arm_gen_setmem (operands))
7240 DONE;
7241
7242 FAIL;
7243 })
7244
7245
7246 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
7247 ;; We could let this apply for blocks of less than this, but it clobbers so
7248 ;; many registers that there is then probably a better way.
7249
7250 (define_expand "movmemqi"
7251 [(match_operand:BLK 0 "general_operand" "")
7252 (match_operand:BLK 1 "general_operand" "")
7253 (match_operand:SI 2 "const_int_operand" "")
7254 (match_operand:SI 3 "const_int_operand" "")]
7255 ""
7256 "
7257 if (TARGET_32BIT)
7258 {
7259 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7260 && !optimize_function_for_size_p (cfun))
7261 {
7262 if (gen_movmem_ldrd_strd (operands))
7263 DONE;
7264 FAIL;
7265 }
7266
7267 if (arm_gen_movmemqi (operands))
7268 DONE;
7269 FAIL;
7270 }
7271 else /* TARGET_THUMB1 */
7272 {
7273 if ( INTVAL (operands[3]) != 4
7274 || INTVAL (operands[2]) > 48)
7275 FAIL;
7276
7277 thumb_expand_movmemqi (operands);
7278 DONE;
7279 }
7280 "
7281 )
7282 \f
7283
7284 ;; Compare & branch insns
7285 ;; The range calculations are based as follows:
7286 ;; For forward branches, the address calculation returns the address of
7287 ;; the next instruction. This is 2 beyond the branch instruction.
7288 ;; For backward branches, the address calculation returns the address of
7289 ;; the first instruction in this pattern (cmp). This is 2 before the branch
7290 ;; instruction for the shortest sequence, and 4 before the branch instruction
7291 ;; if we have to jump around an unconditional branch.
7292 ;; To the basic branch range the PC offset must be added (this is +4).
7293 ;; So for forward branches we have
7294 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7295 ;; And for backward branches we have
7296 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7297 ;;
7298 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7299 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
7300
7301 (define_expand "cbranchsi4"
7302 [(set (pc) (if_then_else
7303 (match_operator 0 "expandable_comparison_operator"
7304 [(match_operand:SI 1 "s_register_operand" "")
7305 (match_operand:SI 2 "nonmemory_operand" "")])
7306 (label_ref (match_operand 3 "" ""))
7307 (pc)))]
7308 "TARGET_EITHER"
7309 "
7310 if (!TARGET_THUMB1)
7311 {
7312 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7313 FAIL;
7314 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7315 operands[3]));
7316 DONE;
7317 }
7318 if (thumb1_cmpneg_operand (operands[2], SImode))
7319 {
7320 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7321 operands[3], operands[0]));
7322 DONE;
7323 }
7324 if (!thumb1_cmp_operand (operands[2], SImode))
7325 operands[2] = force_reg (SImode, operands[2]);
7326 ")
7327
7328 (define_expand "cbranchsf4"
7329 [(set (pc) (if_then_else
7330 (match_operator 0 "expandable_comparison_operator"
7331 [(match_operand:SF 1 "s_register_operand" "")
7332 (match_operand:SF 2 "vfp_compare_operand" "")])
7333 (label_ref (match_operand 3 "" ""))
7334 (pc)))]
7335 "TARGET_32BIT && TARGET_HARD_FLOAT"
7336 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7337 operands[3])); DONE;"
7338 )
7339
7340 (define_expand "cbranchdf4"
7341 [(set (pc) (if_then_else
7342 (match_operator 0 "expandable_comparison_operator"
7343 [(match_operand:DF 1 "s_register_operand" "")
7344 (match_operand:DF 2 "vfp_compare_operand" "")])
7345 (label_ref (match_operand 3 "" ""))
7346 (pc)))]
7347 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7348 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7349 operands[3])); DONE;"
7350 )
7351
7352 (define_expand "cbranchdi4"
7353 [(set (pc) (if_then_else
7354 (match_operator 0 "expandable_comparison_operator"
7355 [(match_operand:DI 1 "s_register_operand" "")
7356 (match_operand:DI 2 "cmpdi_operand" "")])
7357 (label_ref (match_operand 3 "" ""))
7358 (pc)))]
7359 "TARGET_32BIT"
7360 "{
7361 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7362 FAIL;
7363 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7364 operands[3]));
7365 DONE;
7366 }"
7367 )
7368
7369 ;; Comparison and test insns
7370
7371 (define_insn "*arm_cmpsi_insn"
7372 [(set (reg:CC CC_REGNUM)
7373 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7374 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
7375 "TARGET_32BIT"
7376 "@
7377 cmp%?\\t%0, %1
7378 cmp%?\\t%0, %1
7379 cmp%?\\t%0, %1
7380 cmp%?\\t%0, %1
7381 cmn%?\\t%0, #%n1"
7382 [(set_attr "conds" "set")
7383 (set_attr "arch" "t2,t2,any,any,any")
7384 (set_attr "length" "2,2,4,4,4")
7385 (set_attr "predicable" "yes")
7386 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
7387 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
7388 )
7389
7390 (define_insn "*cmpsi_shiftsi"
7391 [(set (reg:CC CC_REGNUM)
7392 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
7393 (match_operator:SI 3 "shift_operator"
7394 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7395 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
7396 "TARGET_32BIT"
7397 "cmp\\t%0, %1%S3"
7398 [(set_attr "conds" "set")
7399 (set_attr "shift" "1")
7400 (set_attr "arch" "32,a,a")
7401 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
7402
7403 (define_insn "*cmpsi_shiftsi_swp"
7404 [(set (reg:CC_SWP CC_REGNUM)
7405 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7406 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7407 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7408 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
7409 "TARGET_32BIT"
7410 "cmp%?\\t%0, %1%S3"
7411 [(set_attr "conds" "set")
7412 (set_attr "shift" "1")
7413 (set_attr "arch" "32,a,a")
7414 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
7415
7416 (define_insn "*arm_cmpsi_negshiftsi_si"
7417 [(set (reg:CC_Z CC_REGNUM)
7418 (compare:CC_Z
7419 (neg:SI (match_operator:SI 1 "shift_operator"
7420 [(match_operand:SI 2 "s_register_operand" "r")
7421 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7422 (match_operand:SI 0 "s_register_operand" "r")))]
7423 "TARGET_ARM"
7424 "cmn%?\\t%0, %2%S1"
7425 [(set_attr "conds" "set")
7426 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7427 (const_string "alus_shift_imm")
7428 (const_string "alus_shift_reg")))
7429 (set_attr "predicable" "yes")]
7430 )
7431
7432 ;; DImode comparisons. The generic code generates branches that
7433 ;; if-conversion cannot reduce to a conditional compare, so we do
7434 ;; that directly.
7435
7436 (define_insn_and_split "*arm_cmpdi_insn"
7437 [(set (reg:CC_NCV CC_REGNUM)
7438 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7439 (match_operand:DI 1 "arm_di_operand" "rDi")))
7440 (clobber (match_scratch:SI 2 "=r"))]
7441 "TARGET_32BIT"
7442 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7443 "&& reload_completed"
7444 [(set (reg:CC CC_REGNUM)
7445 (compare:CC (match_dup 0) (match_dup 1)))
7446 (parallel [(set (reg:CC CC_REGNUM)
7447 (compare:CC (match_dup 3) (match_dup 4)))
7448 (set (match_dup 2)
7449 (minus:SI (match_dup 5)
7450 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7451 {
7452 operands[3] = gen_highpart (SImode, operands[0]);
7453 operands[0] = gen_lowpart (SImode, operands[0]);
7454 if (CONST_INT_P (operands[1]))
7455 {
7456 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);
7457 if (operands[4] == const0_rtx)
7458 operands[5] = operands[3];
7459 else
7460 operands[5] = gen_rtx_PLUS (SImode, operands[3],
7461 gen_int_mode (-UINTVAL (operands[4]),
7462 SImode));
7463 }
7464 else
7465 {
7466 operands[4] = gen_highpart (SImode, operands[1]);
7467 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7468 }
7469 operands[1] = gen_lowpart (SImode, operands[1]);
7470 operands[2] = gen_lowpart (SImode, operands[2]);
7471 }
7472 [(set_attr "conds" "set")
7473 (set_attr "length" "8")
7474 (set_attr "type" "multiple")]
7475 )
7476
7477 (define_insn_and_split "*arm_cmpdi_unsigned"
7478 [(set (reg:CC_CZ CC_REGNUM)
7479 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7480 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7481
7482 "TARGET_32BIT"
7483 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7484 "&& reload_completed"
7485 [(set (reg:CC CC_REGNUM)
7486 (compare:CC (match_dup 2) (match_dup 3)))
7487 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7488 (set (reg:CC CC_REGNUM)
7489 (compare:CC (match_dup 0) (match_dup 1))))]
7490 {
7491 operands[2] = gen_highpart (SImode, operands[0]);
7492 operands[0] = gen_lowpart (SImode, operands[0]);
7493 if (CONST_INT_P (operands[1]))
7494 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7495 else
7496 operands[3] = gen_highpart (SImode, operands[1]);
7497 operands[1] = gen_lowpart (SImode, operands[1]);
7498 }
7499 [(set_attr "conds" "set")
7500 (set_attr "enabled_for_short_it" "yes,yes,no,*")
7501 (set_attr "arch" "t2,t2,t2,a")
7502 (set_attr "length" "6,6,10,8")
7503 (set_attr "type" "multiple")]
7504 )
7505
7506 (define_insn "*arm_cmpdi_zero"
7507 [(set (reg:CC_Z CC_REGNUM)
7508 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7509 (const_int 0)))
7510 (clobber (match_scratch:SI 1 "=r"))]
7511 "TARGET_32BIT"
7512 "orrs%?\\t%1, %Q0, %R0"
7513 [(set_attr "conds" "set")
7514 (set_attr "type" "logics_reg")]
7515 )
7516
7517 ; This insn allows redundant compares to be removed by cse, nothing should
7518 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7519 ; is deleted later on. The match_dup will match the mode here, so that
7520 ; mode changes of the condition codes aren't lost by this even though we don't
7521 ; specify what they are.
7522
7523 (define_insn "*deleted_compare"
7524 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7525 "TARGET_32BIT"
7526 "\\t%@ deleted compare"
7527 [(set_attr "conds" "set")
7528 (set_attr "length" "0")
7529 (set_attr "type" "no_insn")]
7530 )
7531
7532 \f
7533 ;; Conditional branch insns
7534
7535 (define_expand "cbranch_cc"
7536 [(set (pc)
7537 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7538 (match_operand 2 "" "")])
7539 (label_ref (match_operand 3 "" ""))
7540 (pc)))]
7541 "TARGET_32BIT"
7542 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7543 operands[1], operands[2], NULL_RTX);
7544 operands[2] = const0_rtx;"
7545 )
7546
7547 ;;
7548 ;; Patterns to match conditional branch insns.
7549 ;;
7550
7551 (define_insn "arm_cond_branch"
7552 [(set (pc)
7553 (if_then_else (match_operator 1 "arm_comparison_operator"
7554 [(match_operand 2 "cc_register" "") (const_int 0)])
7555 (label_ref (match_operand 0 "" ""))
7556 (pc)))]
7557 "TARGET_32BIT"
7558 "*
7559 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7560 {
7561 arm_ccfsm_state += 2;
7562 return \"\";
7563 }
7564 return \"b%d1\\t%l0\";
7565 "
7566 [(set_attr "conds" "use")
7567 (set_attr "type" "branch")
7568 (set (attr "length")
7569 (if_then_else
7570 (and (match_test "TARGET_THUMB2")
7571 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7572 (le (minus (match_dup 0) (pc)) (const_int 256))))
7573 (const_int 2)
7574 (const_int 4)))]
7575 )
7576
7577 (define_insn "*arm_cond_branch_reversed"
7578 [(set (pc)
7579 (if_then_else (match_operator 1 "arm_comparison_operator"
7580 [(match_operand 2 "cc_register" "") (const_int 0)])
7581 (pc)
7582 (label_ref (match_operand 0 "" ""))))]
7583 "TARGET_32BIT"
7584 "*
7585 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7586 {
7587 arm_ccfsm_state += 2;
7588 return \"\";
7589 }
7590 return \"b%D1\\t%l0\";
7591 "
7592 [(set_attr "conds" "use")
7593 (set_attr "type" "branch")
7594 (set (attr "length")
7595 (if_then_else
7596 (and (match_test "TARGET_THUMB2")
7597 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7598 (le (minus (match_dup 0) (pc)) (const_int 256))))
7599 (const_int 2)
7600 (const_int 4)))]
7601 )
7602
7603 \f
7604
7605 ; scc insns
7606
7607 (define_expand "cstore_cc"
7608 [(set (match_operand:SI 0 "s_register_operand" "")
7609 (match_operator:SI 1 "" [(match_operand 2 "" "")
7610 (match_operand 3 "" "")]))]
7611 "TARGET_32BIT"
7612 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7613 operands[2], operands[3], NULL_RTX);
7614 operands[3] = const0_rtx;"
7615 )
7616
7617 (define_insn_and_split "*mov_scc"
7618 [(set (match_operand:SI 0 "s_register_operand" "=r")
7619 (match_operator:SI 1 "arm_comparison_operator_mode"
7620 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7621 "TARGET_ARM"
7622 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7623 "TARGET_ARM"
7624 [(set (match_dup 0)
7625 (if_then_else:SI (match_dup 1)
7626 (const_int 1)
7627 (const_int 0)))]
7628 ""
7629 [(set_attr "conds" "use")
7630 (set_attr "length" "8")
7631 (set_attr "type" "multiple")]
7632 )
7633
7634 (define_insn_and_split "*mov_negscc"
7635 [(set (match_operand:SI 0 "s_register_operand" "=r")
7636 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
7637 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7638 "TARGET_ARM"
7639 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7640 "TARGET_ARM"
7641 [(set (match_dup 0)
7642 (if_then_else:SI (match_dup 1)
7643 (match_dup 3)
7644 (const_int 0)))]
7645 {
7646 operands[3] = GEN_INT (~0);
7647 }
7648 [(set_attr "conds" "use")
7649 (set_attr "length" "8")
7650 (set_attr "type" "multiple")]
7651 )
7652
7653 (define_insn_and_split "*mov_notscc"
7654 [(set (match_operand:SI 0 "s_register_operand" "=r")
7655 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7656 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7657 "TARGET_ARM"
7658 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7659 "TARGET_ARM"
7660 [(set (match_dup 0)
7661 (if_then_else:SI (match_dup 1)
7662 (match_dup 3)
7663 (match_dup 4)))]
7664 {
7665 operands[3] = GEN_INT (~1);
7666 operands[4] = GEN_INT (~0);
7667 }
7668 [(set_attr "conds" "use")
7669 (set_attr "length" "8")
7670 (set_attr "type" "multiple")]
7671 )
7672
7673 (define_expand "cstoresi4"
7674 [(set (match_operand:SI 0 "s_register_operand" "")
7675 (match_operator:SI 1 "expandable_comparison_operator"
7676 [(match_operand:SI 2 "s_register_operand" "")
7677 (match_operand:SI 3 "reg_or_int_operand" "")]))]
7678 "TARGET_32BIT || TARGET_THUMB1"
7679 "{
7680 rtx op3, scratch, scratch2;
7681
7682 if (!TARGET_THUMB1)
7683 {
7684 if (!arm_add_operand (operands[3], SImode))
7685 operands[3] = force_reg (SImode, operands[3]);
7686 emit_insn (gen_cstore_cc (operands[0], operands[1],
7687 operands[2], operands[3]));
7688 DONE;
7689 }
7690
7691 if (operands[3] == const0_rtx)
7692 {
7693 switch (GET_CODE (operands[1]))
7694 {
7695 case EQ:
7696 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7697 break;
7698
7699 case NE:
7700 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7701 break;
7702
7703 case LE:
7704 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7705 NULL_RTX, 0, OPTAB_WIDEN);
7706 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7707 NULL_RTX, 0, OPTAB_WIDEN);
7708 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7709 operands[0], 1, OPTAB_WIDEN);
7710 break;
7711
7712 case GE:
7713 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7714 NULL_RTX, 1);
7715 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7716 NULL_RTX, 1, OPTAB_WIDEN);
7717 break;
7718
7719 case GT:
7720 scratch = expand_binop (SImode, ashr_optab, operands[2],
7721 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7722 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7723 NULL_RTX, 0, OPTAB_WIDEN);
7724 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7725 0, OPTAB_WIDEN);
7726 break;
7727
7728 /* LT is handled by generic code. No need for unsigned with 0. */
7729 default:
7730 FAIL;
7731 }
7732 DONE;
7733 }
7734
7735 switch (GET_CODE (operands[1]))
7736 {
7737 case EQ:
7738 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7739 NULL_RTX, 0, OPTAB_WIDEN);
7740 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7741 break;
7742
7743 case NE:
7744 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7745 NULL_RTX, 0, OPTAB_WIDEN);
7746 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7747 break;
7748
7749 case LE:
7750 op3 = force_reg (SImode, operands[3]);
7751
7752 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7753 NULL_RTX, 1, OPTAB_WIDEN);
7754 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7755 NULL_RTX, 0, OPTAB_WIDEN);
7756 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7757 op3, operands[2]));
7758 break;
7759
7760 case GE:
7761 op3 = operands[3];
7762 if (!thumb1_cmp_operand (op3, SImode))
7763 op3 = force_reg (SImode, op3);
7764 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7765 NULL_RTX, 0, OPTAB_WIDEN);
7766 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7767 NULL_RTX, 1, OPTAB_WIDEN);
7768 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7769 operands[2], op3));
7770 break;
7771
7772 case LEU:
7773 op3 = force_reg (SImode, operands[3]);
7774 scratch = force_reg (SImode, const0_rtx);
7775 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7776 op3, operands[2]));
7777 break;
7778
7779 case GEU:
7780 op3 = operands[3];
7781 if (!thumb1_cmp_operand (op3, SImode))
7782 op3 = force_reg (SImode, op3);
7783 scratch = force_reg (SImode, const0_rtx);
7784 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7785 operands[2], op3));
7786 break;
7787
7788 case LTU:
7789 op3 = operands[3];
7790 if (!thumb1_cmp_operand (op3, SImode))
7791 op3 = force_reg (SImode, op3);
7792 scratch = gen_reg_rtx (SImode);
7793 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7794 break;
7795
7796 case GTU:
7797 op3 = force_reg (SImode, operands[3]);
7798 scratch = gen_reg_rtx (SImode);
7799 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7800 break;
7801
7802 /* No good sequences for GT, LT. */
7803 default:
7804 FAIL;
7805 }
7806 DONE;
7807 }")
7808
7809 (define_expand "cstorehf4"
7810 [(set (match_operand:SI 0 "s_register_operand")
7811 (match_operator:SI 1 "expandable_comparison_operator"
7812 [(match_operand:HF 2 "s_register_operand")
7813 (match_operand:HF 3 "vfp_compare_operand")]))]
7814 "TARGET_VFP_FP16INST"
7815 {
7816 if (!arm_validize_comparison (&operands[1],
7817 &operands[2],
7818 &operands[3]))
7819 FAIL;
7820
7821 emit_insn (gen_cstore_cc (operands[0], operands[1],
7822 operands[2], operands[3]));
7823 DONE;
7824 }
7825 )
7826
7827 (define_expand "cstoresf4"
7828 [(set (match_operand:SI 0 "s_register_operand" "")
7829 (match_operator:SI 1 "expandable_comparison_operator"
7830 [(match_operand:SF 2 "s_register_operand" "")
7831 (match_operand:SF 3 "vfp_compare_operand" "")]))]
7832 "TARGET_32BIT && TARGET_HARD_FLOAT"
7833 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7834 operands[2], operands[3])); DONE;"
7835 )
7836
7837 (define_expand "cstoredf4"
7838 [(set (match_operand:SI 0 "s_register_operand" "")
7839 (match_operator:SI 1 "expandable_comparison_operator"
7840 [(match_operand:DF 2 "s_register_operand" "")
7841 (match_operand:DF 3 "vfp_compare_operand" "")]))]
7842 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7843 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7844 operands[2], operands[3])); DONE;"
7845 )
7846
7847 (define_expand "cstoredi4"
7848 [(set (match_operand:SI 0 "s_register_operand" "")
7849 (match_operator:SI 1 "expandable_comparison_operator"
7850 [(match_operand:DI 2 "s_register_operand" "")
7851 (match_operand:DI 3 "cmpdi_operand" "")]))]
7852 "TARGET_32BIT"
7853 "{
7854 if (!arm_validize_comparison (&operands[1],
7855 &operands[2],
7856 &operands[3]))
7857 FAIL;
7858 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7859 operands[3]));
7860 DONE;
7861 }"
7862 )
7863
7864 \f
7865 ;; Conditional move insns
7866
7867 (define_expand "movsicc"
7868 [(set (match_operand:SI 0 "s_register_operand" "")
7869 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
7870 (match_operand:SI 2 "arm_not_operand" "")
7871 (match_operand:SI 3 "arm_not_operand" "")))]
7872 "TARGET_32BIT"
7873 "
7874 {
7875 enum rtx_code code;
7876 rtx ccreg;
7877
7878 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7879 &XEXP (operands[1], 1)))
7880 FAIL;
7881
7882 code = GET_CODE (operands[1]);
7883 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7884 XEXP (operands[1], 1), NULL_RTX);
7885 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7886 }"
7887 )
7888
7889 (define_expand "movhfcc"
7890 [(set (match_operand:HF 0 "s_register_operand")
7891 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7892 (match_operand:HF 2 "s_register_operand")
7893 (match_operand:HF 3 "s_register_operand")))]
7894 "TARGET_VFP_FP16INST"
7895 "
7896 {
7897 enum rtx_code code = GET_CODE (operands[1]);
7898 rtx ccreg;
7899
7900 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7901 &XEXP (operands[1], 1)))
7902 FAIL;
7903
7904 code = GET_CODE (operands[1]);
7905 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7906 XEXP (operands[1], 1), NULL_RTX);
7907 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7908 }"
7909 )
7910
7911 (define_expand "movsfcc"
7912 [(set (match_operand:SF 0 "s_register_operand" "")
7913 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
7914 (match_operand:SF 2 "s_register_operand" "")
7915 (match_operand:SF 3 "s_register_operand" "")))]
7916 "TARGET_32BIT && TARGET_HARD_FLOAT"
7917 "
7918 {
7919 enum rtx_code code = GET_CODE (operands[1]);
7920 rtx ccreg;
7921
7922 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7923 &XEXP (operands[1], 1)))
7924 FAIL;
7925
7926 code = GET_CODE (operands[1]);
7927 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7928 XEXP (operands[1], 1), NULL_RTX);
7929 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7930 }"
7931 )
7932
7933 (define_expand "movdfcc"
7934 [(set (match_operand:DF 0 "s_register_operand" "")
7935 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
7936 (match_operand:DF 2 "s_register_operand" "")
7937 (match_operand:DF 3 "s_register_operand" "")))]
7938 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7939 "
7940 {
7941 enum rtx_code code = GET_CODE (operands[1]);
7942 rtx ccreg;
7943
7944 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7945 &XEXP (operands[1], 1)))
7946 FAIL;
7947 code = GET_CODE (operands[1]);
7948 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7949 XEXP (operands[1], 1), NULL_RTX);
7950 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7951 }"
7952 )
7953
7954 (define_insn "*cmov<mode>"
7955 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7956 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7957 [(match_operand 2 "cc_register" "") (const_int 0)])
7958 (match_operand:SDF 3 "s_register_operand"
7959 "<F_constraint>")
7960 (match_operand:SDF 4 "s_register_operand"
7961 "<F_constraint>")))]
7962 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
7963 "*
7964 {
7965 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7966 switch (code)
7967 {
7968 case ARM_GE:
7969 case ARM_GT:
7970 case ARM_EQ:
7971 case ARM_VS:
7972 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7973 case ARM_LT:
7974 case ARM_LE:
7975 case ARM_NE:
7976 case ARM_VC:
7977 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7978 default:
7979 gcc_unreachable ();
7980 }
7981 return \"\";
7982 }"
7983 [(set_attr "conds" "use")
7984 (set_attr "type" "fcsel")]
7985 )
7986
7987 (define_insn "*cmovhf"
7988 [(set (match_operand:HF 0 "s_register_operand" "=t")
7989 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7990 [(match_operand 2 "cc_register" "") (const_int 0)])
7991 (match_operand:HF 3 "s_register_operand" "t")
7992 (match_operand:HF 4 "s_register_operand" "t")))]
7993 "TARGET_VFP_FP16INST"
7994 "*
7995 {
7996 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7997 switch (code)
7998 {
7999 case ARM_GE:
8000 case ARM_GT:
8001 case ARM_EQ:
8002 case ARM_VS:
8003 return \"vsel%d1.f16\\t%0, %3, %4\";
8004 case ARM_LT:
8005 case ARM_LE:
8006 case ARM_NE:
8007 case ARM_VC:
8008 return \"vsel%D1.f16\\t%0, %4, %3\";
8009 default:
8010 gcc_unreachable ();
8011 }
8012 return \"\";
8013 }"
8014 [(set_attr "conds" "use")
8015 (set_attr "type" "fcsel")]
8016 )
8017
8018 (define_insn_and_split "*movsicc_insn"
8019 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8020 (if_then_else:SI
8021 (match_operator 3 "arm_comparison_operator"
8022 [(match_operand 4 "cc_register" "") (const_int 0)])
8023 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8024 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8025 "TARGET_ARM"
8026 "@
8027 mov%D3\\t%0, %2
8028 mvn%D3\\t%0, #%B2
8029 mov%d3\\t%0, %1
8030 mvn%d3\\t%0, #%B1
8031 #
8032 #
8033 #
8034 #"
8035 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8036 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8037 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8038 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8039 "&& reload_completed"
8040 [(const_int 0)]
8041 {
8042 enum rtx_code rev_code;
8043 machine_mode mode;
8044 rtx rev_cond;
8045
8046 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8047 operands[3],
8048 gen_rtx_SET (operands[0], operands[1])));
8049
8050 rev_code = GET_CODE (operands[3]);
8051 mode = GET_MODE (operands[4]);
8052 if (mode == CCFPmode || mode == CCFPEmode)
8053 rev_code = reverse_condition_maybe_unordered (rev_code);
8054 else
8055 rev_code = reverse_condition (rev_code);
8056
8057 rev_cond = gen_rtx_fmt_ee (rev_code,
8058 VOIDmode,
8059 operands[4],
8060 const0_rtx);
8061 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
8062 rev_cond,
8063 gen_rtx_SET (operands[0], operands[2])));
8064 DONE;
8065 }
8066 [(set_attr "length" "4,4,4,4,8,8,8,8")
8067 (set_attr "conds" "use")
8068 (set_attr_alternative "type"
8069 [(if_then_else (match_operand 2 "const_int_operand" "")
8070 (const_string "mov_imm")
8071 (const_string "mov_reg"))
8072 (const_string "mvn_imm")
8073 (if_then_else (match_operand 1 "const_int_operand" "")
8074 (const_string "mov_imm")
8075 (const_string "mov_reg"))
8076 (const_string "mvn_imm")
8077 (const_string "multiple")
8078 (const_string "multiple")
8079 (const_string "multiple")
8080 (const_string "multiple")])]
8081 )
8082
8083 (define_insn "*movsfcc_soft_insn"
8084 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8085 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8086 [(match_operand 4 "cc_register" "") (const_int 0)])
8087 (match_operand:SF 1 "s_register_operand" "0,r")
8088 (match_operand:SF 2 "s_register_operand" "r,0")))]
8089 "TARGET_ARM && TARGET_SOFT_FLOAT"
8090 "@
8091 mov%D3\\t%0, %2
8092 mov%d3\\t%0, %1"
8093 [(set_attr "conds" "use")
8094 (set_attr "type" "mov_reg")]
8095 )
8096
8097 \f
8098 ;; Jump and linkage insns
8099
8100 (define_expand "jump"
8101 [(set (pc)
8102 (label_ref (match_operand 0 "" "")))]
8103 "TARGET_EITHER"
8104 ""
8105 )
8106
8107 (define_insn "*arm_jump"
8108 [(set (pc)
8109 (label_ref (match_operand 0 "" "")))]
8110 "TARGET_32BIT"
8111 "*
8112 {
8113 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8114 {
8115 arm_ccfsm_state += 2;
8116 return \"\";
8117 }
8118 return \"b%?\\t%l0\";
8119 }
8120 "
8121 [(set_attr "predicable" "yes")
8122 (set (attr "length")
8123 (if_then_else
8124 (and (match_test "TARGET_THUMB2")
8125 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8126 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8127 (const_int 2)
8128 (const_int 4)))
8129 (set_attr "type" "branch")]
8130 )
8131
8132 (define_expand "call"
8133 [(parallel [(call (match_operand 0 "memory_operand" "")
8134 (match_operand 1 "general_operand" ""))
8135 (use (match_operand 2 "" ""))
8136 (clobber (reg:SI LR_REGNUM))])]
8137 "TARGET_EITHER"
8138 "
8139 {
8140 rtx callee, pat;
8141 tree addr = MEM_EXPR (operands[0]);
8142
8143 /* In an untyped call, we can get NULL for operand 2. */
8144 if (operands[2] == NULL_RTX)
8145 operands[2] = const0_rtx;
8146
8147 /* Decide if we should generate indirect calls by loading the
8148 32-bit address of the callee into a register before performing the
8149 branch and link. */
8150 callee = XEXP (operands[0], 0);
8151 if (GET_CODE (callee) == SYMBOL_REF
8152 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8153 : !REG_P (callee))
8154 XEXP (operands[0], 0) = force_reg (Pmode, callee);
8155
8156 if (detect_cmse_nonsecure_call (addr))
8157 {
8158 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8159 operands[2]);
8160 emit_call_insn (pat);
8161 }
8162 else
8163 {
8164 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8165 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8166 }
8167 DONE;
8168 }"
8169 )
8170
8171 (define_expand "call_internal"
8172 [(parallel [(call (match_operand 0 "memory_operand" "")
8173 (match_operand 1 "general_operand" ""))
8174 (use (match_operand 2 "" ""))
8175 (clobber (reg:SI LR_REGNUM))])])
8176
8177 (define_expand "nonsecure_call_internal"
8178 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8179 UNSPEC_NONSECURE_MEM)
8180 (match_operand 1 "general_operand" ""))
8181 (use (match_operand 2 "" ""))
8182 (clobber (reg:SI LR_REGNUM))])]
8183 "use_cmse"
8184 "
8185 {
8186 rtx tmp;
8187 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
8188 gen_rtx_REG (SImode, R4_REGNUM),
8189 SImode);
8190
8191 operands[0] = replace_equiv_address (operands[0], tmp);
8192 }")
8193
8194 (define_insn "*call_reg_armv5"
8195 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8196 (match_operand 1 "" ""))
8197 (use (match_operand 2 "" ""))
8198 (clobber (reg:SI LR_REGNUM))]
8199 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
8200 "blx%?\\t%0"
8201 [(set_attr "type" "call")]
8202 )
8203
8204 (define_insn "*call_reg_arm"
8205 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8206 (match_operand 1 "" ""))
8207 (use (match_operand 2 "" ""))
8208 (clobber (reg:SI LR_REGNUM))]
8209 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
8210 "*
8211 return output_call (operands);
8212 "
8213 ;; length is worst case, normally it is only two
8214 [(set_attr "length" "12")
8215 (set_attr "type" "call")]
8216 )
8217
8218
8219 (define_expand "call_value"
8220 [(parallel [(set (match_operand 0 "" "")
8221 (call (match_operand 1 "memory_operand" "")
8222 (match_operand 2 "general_operand" "")))
8223 (use (match_operand 3 "" ""))
8224 (clobber (reg:SI LR_REGNUM))])]
8225 "TARGET_EITHER"
8226 "
8227 {
8228 rtx pat, callee;
8229 tree addr = MEM_EXPR (operands[1]);
8230
8231 /* In an untyped call, we can get NULL for operand 2. */
8232 if (operands[3] == 0)
8233 operands[3] = const0_rtx;
8234
8235 /* Decide if we should generate indirect calls by loading the
8236 32-bit address of the callee into a register before performing the
8237 branch and link. */
8238 callee = XEXP (operands[1], 0);
8239 if (GET_CODE (callee) == SYMBOL_REF
8240 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8241 : !REG_P (callee))
8242 XEXP (operands[1], 0) = force_reg (Pmode, callee);
8243
8244 if (detect_cmse_nonsecure_call (addr))
8245 {
8246 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8247 operands[2], operands[3]);
8248 emit_call_insn (pat);
8249 }
8250 else
8251 {
8252 pat = gen_call_value_internal (operands[0], operands[1],
8253 operands[2], operands[3]);
8254 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8255 }
8256 DONE;
8257 }"
8258 )
8259
8260 (define_expand "call_value_internal"
8261 [(parallel [(set (match_operand 0 "" "")
8262 (call (match_operand 1 "memory_operand" "")
8263 (match_operand 2 "general_operand" "")))
8264 (use (match_operand 3 "" ""))
8265 (clobber (reg:SI LR_REGNUM))])])
8266
8267 (define_expand "nonsecure_call_value_internal"
8268 [(parallel [(set (match_operand 0 "" "")
8269 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8270 UNSPEC_NONSECURE_MEM)
8271 (match_operand 2 "general_operand" "")))
8272 (use (match_operand 3 "" ""))
8273 (clobber (reg:SI LR_REGNUM))])]
8274 "use_cmse"
8275 "
8276 {
8277 rtx tmp;
8278 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
8279 gen_rtx_REG (SImode, R4_REGNUM),
8280 SImode);
8281
8282 operands[1] = replace_equiv_address (operands[1], tmp);
8283 }")
8284
8285 (define_insn "*call_value_reg_armv5"
8286 [(set (match_operand 0 "" "")
8287 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8288 (match_operand 2 "" "")))
8289 (use (match_operand 3 "" ""))
8290 (clobber (reg:SI LR_REGNUM))]
8291 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
8292 "blx%?\\t%1"
8293 [(set_attr "type" "call")]
8294 )
8295
8296 (define_insn "*call_value_reg_arm"
8297 [(set (match_operand 0 "" "")
8298 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8299 (match_operand 2 "" "")))
8300 (use (match_operand 3 "" ""))
8301 (clobber (reg:SI LR_REGNUM))]
8302 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
8303 "*
8304 return output_call (&operands[1]);
8305 "
8306 [(set_attr "length" "12")
8307 (set_attr "type" "call")]
8308 )
8309
8310 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8311 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8312
8313 (define_insn "*call_symbol"
8314 [(call (mem:SI (match_operand:SI 0 "" ""))
8315 (match_operand 1 "" ""))
8316 (use (match_operand 2 "" ""))
8317 (clobber (reg:SI LR_REGNUM))]
8318 "TARGET_32BIT
8319 && !SIBLING_CALL_P (insn)
8320 && (GET_CODE (operands[0]) == SYMBOL_REF)
8321 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8322 "*
8323 {
8324 rtx op = operands[0];
8325
8326 /* Switch mode now when possible. */
8327 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8328 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8329 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8330
8331 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8332 }"
8333 [(set_attr "type" "call")]
8334 )
8335
8336 (define_insn "*call_value_symbol"
8337 [(set (match_operand 0 "" "")
8338 (call (mem:SI (match_operand:SI 1 "" ""))
8339 (match_operand:SI 2 "" "")))
8340 (use (match_operand 3 "" ""))
8341 (clobber (reg:SI LR_REGNUM))]
8342 "TARGET_32BIT
8343 && !SIBLING_CALL_P (insn)
8344 && (GET_CODE (operands[1]) == SYMBOL_REF)
8345 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8346 "*
8347 {
8348 rtx op = operands[1];
8349
8350 /* Switch mode now when possible. */
8351 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8352 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8353 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
8354
8355 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8356 }"
8357 [(set_attr "type" "call")]
8358 )
8359
8360 (define_expand "sibcall_internal"
8361 [(parallel [(call (match_operand 0 "memory_operand" "")
8362 (match_operand 1 "general_operand" ""))
8363 (return)
8364 (use (match_operand 2 "" ""))])])
8365
8366 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8367 (define_expand "sibcall"
8368 [(parallel [(call (match_operand 0 "memory_operand" "")
8369 (match_operand 1 "general_operand" ""))
8370 (return)
8371 (use (match_operand 2 "" ""))])]
8372 "TARGET_32BIT"
8373 "
8374 {
8375 rtx pat;
8376
8377 if ((!REG_P (XEXP (operands[0], 0))
8378 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8379 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8380 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
8381 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8382
8383 if (operands[2] == NULL_RTX)
8384 operands[2] = const0_rtx;
8385
8386 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8387 arm_emit_call_insn (pat, operands[0], true);
8388 DONE;
8389 }"
8390 )
8391
8392 (define_expand "sibcall_value_internal"
8393 [(parallel [(set (match_operand 0 "" "")
8394 (call (match_operand 1 "memory_operand" "")
8395 (match_operand 2 "general_operand" "")))
8396 (return)
8397 (use (match_operand 3 "" ""))])])
8398
8399 (define_expand "sibcall_value"
8400 [(parallel [(set (match_operand 0 "" "")
8401 (call (match_operand 1 "memory_operand" "")
8402 (match_operand 2 "general_operand" "")))
8403 (return)
8404 (use (match_operand 3 "" ""))])]
8405 "TARGET_32BIT"
8406 "
8407 {
8408 rtx pat;
8409
8410 if ((!REG_P (XEXP (operands[1], 0))
8411 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8412 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8413 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
8414 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8415
8416 if (operands[3] == NULL_RTX)
8417 operands[3] = const0_rtx;
8418
8419 pat = gen_sibcall_value_internal (operands[0], operands[1],
8420 operands[2], operands[3]);
8421 arm_emit_call_insn (pat, operands[1], true);
8422 DONE;
8423 }"
8424 )
8425
8426 (define_insn "*sibcall_insn"
8427 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
8428 (match_operand 1 "" ""))
8429 (return)
8430 (use (match_operand 2 "" ""))]
8431 "TARGET_32BIT && SIBLING_CALL_P (insn)"
8432 "*
8433 if (which_alternative == 1)
8434 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8435 else
8436 {
8437 if (arm_arch5t || arm_arch4t)
8438 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
8439 else
8440 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8441 }
8442 "
8443 [(set_attr "type" "call")]
8444 )
8445
8446 (define_insn "*sibcall_value_insn"
8447 [(set (match_operand 0 "" "")
8448 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
8449 (match_operand 2 "" "")))
8450 (return)
8451 (use (match_operand 3 "" ""))]
8452 "TARGET_32BIT && SIBLING_CALL_P (insn)"
8453 "*
8454 if (which_alternative == 1)
8455 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8456 else
8457 {
8458 if (arm_arch5t || arm_arch4t)
8459 return \"bx%?\\t%1\";
8460 else
8461 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8462 }
8463 "
8464 [(set_attr "type" "call")]
8465 )
8466
8467 (define_expand "<return_str>return"
8468 [(RETURNS)]
8469 "(TARGET_ARM || (TARGET_THUMB2
8470 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8471 && !IS_STACKALIGN (arm_current_func_type ())))
8472 <return_cond_false>"
8473 "
8474 {
8475 if (TARGET_THUMB2)
8476 {
8477 thumb2_expand_return (<return_simple_p>);
8478 DONE;
8479 }
8480 }
8481 "
8482 )
8483
8484 ;; Often the return insn will be the same as loading from memory, so set attr
8485 (define_insn "*arm_return"
8486 [(return)]
8487 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8488 "*
8489 {
8490 if (arm_ccfsm_state == 2)
8491 {
8492 arm_ccfsm_state += 2;
8493 return \"\";
8494 }
8495 return output_return_instruction (const_true_rtx, true, false, false);
8496 }"
8497 [(set_attr "type" "load_4")
8498 (set_attr "length" "12")
8499 (set_attr "predicable" "yes")]
8500 )
8501
8502 (define_insn "*cond_<return_str>return"
8503 [(set (pc)
8504 (if_then_else (match_operator 0 "arm_comparison_operator"
8505 [(match_operand 1 "cc_register" "") (const_int 0)])
8506 (RETURNS)
8507 (pc)))]
8508 "TARGET_ARM <return_cond_true>"
8509 "*
8510 {
8511 if (arm_ccfsm_state == 2)
8512 {
8513 arm_ccfsm_state += 2;
8514 return \"\";
8515 }
8516 return output_return_instruction (operands[0], true, false,
8517 <return_simple_p>);
8518 }"
8519 [(set_attr "conds" "use")
8520 (set_attr "length" "12")
8521 (set_attr "type" "load_4")]
8522 )
8523
8524 (define_insn "*cond_<return_str>return_inverted"
8525 [(set (pc)
8526 (if_then_else (match_operator 0 "arm_comparison_operator"
8527 [(match_operand 1 "cc_register" "") (const_int 0)])
8528 (pc)
8529 (RETURNS)))]
8530 "TARGET_ARM <return_cond_true>"
8531 "*
8532 {
8533 if (arm_ccfsm_state == 2)
8534 {
8535 arm_ccfsm_state += 2;
8536 return \"\";
8537 }
8538 return output_return_instruction (operands[0], true, true,
8539 <return_simple_p>);
8540 }"
8541 [(set_attr "conds" "use")
8542 (set_attr "length" "12")
8543 (set_attr "type" "load_4")]
8544 )
8545
8546 (define_insn "*arm_simple_return"
8547 [(simple_return)]
8548 "TARGET_ARM"
8549 "*
8550 {
8551 if (arm_ccfsm_state == 2)
8552 {
8553 arm_ccfsm_state += 2;
8554 return \"\";
8555 }
8556 return output_return_instruction (const_true_rtx, true, false, true);
8557 }"
8558 [(set_attr "type" "branch")
8559 (set_attr "length" "4")
8560 (set_attr "predicable" "yes")]
8561 )
8562
8563 ;; Generate a sequence of instructions to determine if the processor is
8564 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8565 ;; mask.
8566
8567 (define_expand "return_addr_mask"
8568 [(set (match_dup 1)
8569 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8570 (const_int 0)))
8571 (set (match_operand:SI 0 "s_register_operand" "")
8572 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8573 (const_int -1)
8574 (const_int 67108860)))] ; 0x03fffffc
8575 "TARGET_ARM"
8576 "
8577 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8578 ")
8579
8580 (define_insn "*check_arch2"
8581 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8582 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8583 (const_int 0)))]
8584 "TARGET_ARM"
8585 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8586 [(set_attr "length" "8")
8587 (set_attr "conds" "set")
8588 (set_attr "type" "multiple")]
8589 )
8590
8591 ;; Call subroutine returning any type.
8592
8593 (define_expand "untyped_call"
8594 [(parallel [(call (match_operand 0 "" "")
8595 (const_int 0))
8596 (match_operand 1 "" "")
8597 (match_operand 2 "" "")])]
8598 "TARGET_EITHER"
8599 "
8600 {
8601 int i;
8602 rtx par = gen_rtx_PARALLEL (VOIDmode,
8603 rtvec_alloc (XVECLEN (operands[2], 0)));
8604 rtx addr = gen_reg_rtx (Pmode);
8605 rtx mem;
8606 int size = 0;
8607
8608 emit_move_insn (addr, XEXP (operands[1], 0));
8609 mem = change_address (operands[1], BLKmode, addr);
8610
8611 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8612 {
8613 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8614
8615 /* Default code only uses r0 as a return value, but we could
8616 be using anything up to 4 registers. */
8617 if (REGNO (src) == R0_REGNUM)
8618 src = gen_rtx_REG (TImode, R0_REGNUM);
8619
8620 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8621 GEN_INT (size));
8622 size += GET_MODE_SIZE (GET_MODE (src));
8623 }
8624
8625 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
8626
8627 size = 0;
8628
8629 for (i = 0; i < XVECLEN (par, 0); i++)
8630 {
8631 HOST_WIDE_INT offset = 0;
8632 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8633
8634 if (size != 0)
8635 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8636
8637 mem = change_address (mem, GET_MODE (reg), NULL);
8638 if (REGNO (reg) == R0_REGNUM)
8639 {
8640 /* On thumb we have to use a write-back instruction. */
8641 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8642 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8643 size = TARGET_ARM ? 16 : 0;
8644 }
8645 else
8646 {
8647 emit_move_insn (mem, reg);
8648 size = GET_MODE_SIZE (GET_MODE (reg));
8649 }
8650 }
8651
8652 /* The optimizer does not know that the call sets the function value
8653 registers we stored in the result block. We avoid problems by
8654 claiming that all hard registers are used and clobbered at this
8655 point. */
8656 emit_insn (gen_blockage ());
8657
8658 DONE;
8659 }"
8660 )
8661
8662 (define_expand "untyped_return"
8663 [(match_operand:BLK 0 "memory_operand" "")
8664 (match_operand 1 "" "")]
8665 "TARGET_EITHER"
8666 "
8667 {
8668 int i;
8669 rtx addr = gen_reg_rtx (Pmode);
8670 rtx mem;
8671 int size = 0;
8672
8673 emit_move_insn (addr, XEXP (operands[0], 0));
8674 mem = change_address (operands[0], BLKmode, addr);
8675
8676 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8677 {
8678 HOST_WIDE_INT offset = 0;
8679 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8680
8681 if (size != 0)
8682 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8683
8684 mem = change_address (mem, GET_MODE (reg), NULL);
8685 if (REGNO (reg) == R0_REGNUM)
8686 {
8687 /* On thumb we have to use a write-back instruction. */
8688 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8689 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8690 size = TARGET_ARM ? 16 : 0;
8691 }
8692 else
8693 {
8694 emit_move_insn (reg, mem);
8695 size = GET_MODE_SIZE (GET_MODE (reg));
8696 }
8697 }
8698
8699 /* Emit USE insns before the return. */
8700 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8701 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8702
8703 /* Construct the return. */
8704 expand_naked_return ();
8705
8706 DONE;
8707 }"
8708 )
8709
8710 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8711 ;; all of memory. This blocks insns from being moved across this point.
8712
8713 (define_insn "blockage"
8714 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8715 "TARGET_EITHER"
8716 ""
8717 [(set_attr "length" "0")
8718 (set_attr "type" "block")]
8719 )
8720
8721 ;; Since we hard code r0 here use the 'o' constraint to prevent
8722 ;; provoking undefined behaviour in the hardware with putting out
8723 ;; auto-increment operations with potentially r0 as the base register.
8724 (define_insn "probe_stack"
8725 [(set (match_operand:SI 0 "memory_operand" "=o")
8726 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
8727 "TARGET_32BIT"
8728 "str%?\\tr0, %0"
8729 [(set_attr "type" "store_4")
8730 (set_attr "predicable" "yes")]
8731 )
8732
8733 (define_insn "probe_stack_range"
8734 [(set (match_operand:SI 0 "register_operand" "=r")
8735 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8736 (match_operand:SI 2 "register_operand" "r")]
8737 VUNSPEC_PROBE_STACK_RANGE))]
8738 "TARGET_32BIT"
8739 {
8740 return output_probe_stack_range (operands[0], operands[2]);
8741 }
8742 [(set_attr "type" "multiple")
8743 (set_attr "conds" "clob")]
8744 )
8745
8746 ;; Named patterns for stack smashing protection.
8747 (define_expand "stack_protect_combined_set"
8748 [(parallel
8749 [(set (match_operand:SI 0 "memory_operand" "")
8750 (unspec:SI [(match_operand:SI 1 "guard_operand" "")]
8751 UNSPEC_SP_SET))
8752 (clobber (match_scratch:SI 2 ""))
8753 (clobber (match_scratch:SI 3 ""))])]
8754 ""
8755 ""
8756 )
8757
8758 ;; Use a separate insn from the above expand to be able to have the mem outside
8759 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8760 ;; try to reload the guard since we need to control how PIC access is done in
8761 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8762 ;; legitimize_pic_address ()).
8763 (define_insn_and_split "*stack_protect_combined_set_insn"
8764 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8765 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8766 UNSPEC_SP_SET))
8767 (clobber (match_scratch:SI 2 "=&l,&r"))
8768 (clobber (match_scratch:SI 3 "=&l,&r"))]
8769 ""
8770 "#"
8771 "reload_completed"
8772 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8773 UNSPEC_SP_SET))
8774 (clobber (match_dup 2))])]
8775 "
8776 {
8777 if (flag_pic)
8778 {
8779 /* Forces recomputing of GOT base now. */
8780 legitimize_pic_address (operands[1], SImode, operands[2], operands[3],
8781 true /*compute_now*/);
8782 }
8783 else
8784 {
8785 if (address_operand (operands[1], SImode))
8786 operands[2] = operands[1];
8787 else
8788 {
8789 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8790 emit_move_insn (operands[2], mem);
8791 }
8792 }
8793 }"
8794 [(set_attr "arch" "t1,32")]
8795 )
8796
8797 (define_insn "*stack_protect_set_insn"
8798 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8799 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8800 UNSPEC_SP_SET))
8801 (clobber (match_dup 1))]
8802 ""
8803 "@
8804 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1,#0
8805 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1,#0"
8806 [(set_attr "length" "8,12")
8807 (set_attr "conds" "clob,nocond")
8808 (set_attr "type" "multiple")
8809 (set_attr "arch" "t1,32")]
8810 )
8811
8812 (define_expand "stack_protect_combined_test"
8813 [(parallel
8814 [(set (pc)
8815 (if_then_else
8816 (eq (match_operand:SI 0 "memory_operand" "")
8817 (unspec:SI [(match_operand:SI 1 "guard_operand" "")]
8818 UNSPEC_SP_TEST))
8819 (label_ref (match_operand 2))
8820 (pc)))
8821 (clobber (match_scratch:SI 3 ""))
8822 (clobber (match_scratch:SI 4 ""))
8823 (clobber (reg:CC CC_REGNUM))])]
8824 ""
8825 ""
8826 )
8827
8828 ;; Use a separate insn from the above expand to be able to have the mem outside
8829 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8830 ;; try to reload the guard since we need to control how PIC access is done in
8831 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8832 ;; legitimize_pic_address ()).
8833 (define_insn_and_split "*stack_protect_combined_test_insn"
8834 [(set (pc)
8835 (if_then_else
8836 (eq (match_operand:SI 0 "memory_operand" "m,m")
8837 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8838 UNSPEC_SP_TEST))
8839 (label_ref (match_operand 2))
8840 (pc)))
8841 (clobber (match_scratch:SI 3 "=&l,&r"))
8842 (clobber (match_scratch:SI 4 "=&l,&r"))
8843 (clobber (reg:CC CC_REGNUM))]
8844 ""
8845 "#"
8846 "reload_completed"
8847 [(const_int 0)]
8848 {
8849 rtx eq;
8850
8851 if (flag_pic)
8852 {
8853 /* Forces recomputing of GOT base now. */
8854 legitimize_pic_address (operands[1], SImode, operands[3], operands[4],
8855 true /*compute_now*/);
8856 }
8857 else
8858 {
8859 if (address_operand (operands[1], SImode))
8860 operands[3] = operands[1];
8861 else
8862 {
8863 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8864 emit_move_insn (operands[3], mem);
8865 }
8866 }
8867 if (TARGET_32BIT)
8868 {
8869 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8870 operands[3]));
8871 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8872 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8873 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8874 }
8875 else
8876 {
8877 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8878 operands[3]));
8879 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8880 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8881 operands[2]));
8882 }
8883 DONE;
8884 }
8885 [(set_attr "arch" "t1,32")]
8886 )
8887
8888 (define_insn "arm_stack_protect_test_insn"
8889 [(set (reg:CC_Z CC_REGNUM)
8890 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8891 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8892 UNSPEC_SP_TEST)
8893 (const_int 0)))
8894 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8895 (clobber (match_dup 2))]
8896 "TARGET_32BIT"
8897 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8898 [(set_attr "length" "8,12")
8899 (set_attr "conds" "set")
8900 (set_attr "type" "multiple")
8901 (set_attr "arch" "t,32")]
8902 )
8903
8904 (define_expand "casesi"
8905 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8906 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8907 (match_operand:SI 2 "const_int_operand" "") ; total range
8908 (match_operand:SI 3 "" "") ; table label
8909 (match_operand:SI 4 "" "")] ; Out of range label
8910 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
8911 "
8912 {
8913 enum insn_code code;
8914 if (operands[1] != const0_rtx)
8915 {
8916 rtx reg = gen_reg_rtx (SImode);
8917
8918 emit_insn (gen_addsi3 (reg, operands[0],
8919 gen_int_mode (-INTVAL (operands[1]),
8920 SImode)));
8921 operands[0] = reg;
8922 }
8923
8924 if (TARGET_ARM)
8925 code = CODE_FOR_arm_casesi_internal;
8926 else if (TARGET_THUMB1)
8927 code = CODE_FOR_thumb1_casesi_internal_pic;
8928 else if (flag_pic)
8929 code = CODE_FOR_thumb2_casesi_internal_pic;
8930 else
8931 code = CODE_FOR_thumb2_casesi_internal;
8932
8933 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8934 operands[2] = force_reg (SImode, operands[2]);
8935
8936 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8937 operands[3], operands[4]));
8938 DONE;
8939 }"
8940 )
8941
8942 ;; The USE in this pattern is needed to tell flow analysis that this is
8943 ;; a CASESI insn. It has no other purpose.
8944 (define_expand "arm_casesi_internal"
8945 [(parallel [(set (pc)
8946 (if_then_else
8947 (leu (match_operand:SI 0 "s_register_operand")
8948 (match_operand:SI 1 "arm_rhs_operand"))
8949 (match_dup 4)
8950 (label_ref:SI (match_operand 3 ""))))
8951 (clobber (reg:CC CC_REGNUM))
8952 (use (label_ref:SI (match_operand 2 "")))])]
8953 "TARGET_ARM"
8954 {
8955 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8956 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8957 gen_rtx_LABEL_REF (SImode, operands[2]));
8958 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8959 MEM_READONLY_P (operands[4]) = 1;
8960 MEM_NOTRAP_P (operands[4]) = 1;
8961 })
8962
8963 (define_insn "*arm_casesi_internal"
8964 [(parallel [(set (pc)
8965 (if_then_else
8966 (leu (match_operand:SI 0 "s_register_operand" "r")
8967 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8968 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8969 (label_ref:SI (match_operand 2 "" ""))))
8970 (label_ref:SI (match_operand 3 "" ""))))
8971 (clobber (reg:CC CC_REGNUM))
8972 (use (label_ref:SI (match_dup 2)))])]
8973 "TARGET_ARM"
8974 "*
8975 if (flag_pic)
8976 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8977 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8978 "
8979 [(set_attr "conds" "clob")
8980 (set_attr "length" "12")
8981 (set_attr "type" "multiple")]
8982 )
8983
8984 (define_expand "indirect_jump"
8985 [(set (pc)
8986 (match_operand:SI 0 "s_register_operand" ""))]
8987 "TARGET_EITHER"
8988 "
8989 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8990 address and use bx. */
8991 if (TARGET_THUMB2)
8992 {
8993 rtx tmp;
8994 tmp = gen_reg_rtx (SImode);
8995 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8996 operands[0] = tmp;
8997 }
8998 "
8999 )
9000
9001 ;; NB Never uses BX.
9002 (define_insn "*arm_indirect_jump"
9003 [(set (pc)
9004 (match_operand:SI 0 "s_register_operand" "r"))]
9005 "TARGET_ARM"
9006 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
9007 [(set_attr "predicable" "yes")
9008 (set_attr "type" "branch")]
9009 )
9010
9011 (define_insn "*load_indirect_jump"
9012 [(set (pc)
9013 (match_operand:SI 0 "memory_operand" "m"))]
9014 "TARGET_ARM"
9015 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
9016 [(set_attr "type" "load_4")
9017 (set_attr "pool_range" "4096")
9018 (set_attr "neg_pool_range" "4084")
9019 (set_attr "predicable" "yes")]
9020 )
9021
9022 \f
9023 ;; Misc insns
9024
9025 (define_insn "nop"
9026 [(const_int 0)]
9027 "TARGET_EITHER"
9028 "nop"
9029 [(set (attr "length")
9030 (if_then_else (eq_attr "is_thumb" "yes")
9031 (const_int 2)
9032 (const_int 4)))
9033 (set_attr "type" "mov_reg")]
9034 )
9035
9036 (define_insn "trap"
9037 [(trap_if (const_int 1) (const_int 0))]
9038 ""
9039 "*
9040 if (TARGET_ARM)
9041 return \".inst\\t0xe7f000f0\";
9042 else
9043 return \".inst\\t0xdeff\";
9044 "
9045 [(set (attr "length")
9046 (if_then_else (eq_attr "is_thumb" "yes")
9047 (const_int 2)
9048 (const_int 4)))
9049 (set_attr "type" "trap")
9050 (set_attr "conds" "unconditional")]
9051 )
9052
9053 \f
9054 ;; Patterns to allow combination of arithmetic, cond code and shifts
9055
9056 (define_insn "*<arith_shift_insn>_multsi"
9057 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9058 (SHIFTABLE_OPS:SI
9059 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
9060 (match_operand:SI 3 "power_of_two_operand" ""))
9061 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
9062 "TARGET_32BIT"
9063 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
9064 [(set_attr "predicable" "yes")
9065 (set_attr "shift" "2")
9066 (set_attr "arch" "a,t2")
9067 (set_attr "type" "alu_shift_imm")])
9068
9069 (define_insn "*<arith_shift_insn>_shiftsi"
9070 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9071 (SHIFTABLE_OPS:SI
9072 (match_operator:SI 2 "shift_nomul_operator"
9073 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9074 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
9075 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
9076 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
9077 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
9078 [(set_attr "predicable" "yes")
9079 (set_attr "shift" "3")
9080 (set_attr "arch" "a,t2,a")
9081 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
9082
9083 (define_split
9084 [(set (match_operand:SI 0 "s_register_operand" "")
9085 (match_operator:SI 1 "shiftable_operator"
9086 [(match_operator:SI 2 "shiftable_operator"
9087 [(match_operator:SI 3 "shift_operator"
9088 [(match_operand:SI 4 "s_register_operand" "")
9089 (match_operand:SI 5 "reg_or_int_operand" "")])
9090 (match_operand:SI 6 "s_register_operand" "")])
9091 (match_operand:SI 7 "arm_rhs_operand" "")]))
9092 (clobber (match_operand:SI 8 "s_register_operand" ""))]
9093 "TARGET_32BIT"
9094 [(set (match_dup 8)
9095 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9096 (match_dup 6)]))
9097 (set (match_dup 0)
9098 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
9099 "")
9100
9101 (define_insn "*arith_shiftsi_compare0"
9102 [(set (reg:CC_NOOV CC_REGNUM)
9103 (compare:CC_NOOV
9104 (match_operator:SI 1 "shiftable_operator"
9105 [(match_operator:SI 3 "shift_operator"
9106 [(match_operand:SI 4 "s_register_operand" "r,r")
9107 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9108 (match_operand:SI 2 "s_register_operand" "r,r")])
9109 (const_int 0)))
9110 (set (match_operand:SI 0 "s_register_operand" "=r,r")
9111 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
9112 (match_dup 2)]))]
9113 "TARGET_32BIT"
9114 "%i1s%?\\t%0, %2, %4%S3"
9115 [(set_attr "conds" "set")
9116 (set_attr "shift" "4")
9117 (set_attr "arch" "32,a")
9118 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9119
9120 (define_insn "*arith_shiftsi_compare0_scratch"
9121 [(set (reg:CC_NOOV CC_REGNUM)
9122 (compare:CC_NOOV
9123 (match_operator:SI 1 "shiftable_operator"
9124 [(match_operator:SI 3 "shift_operator"
9125 [(match_operand:SI 4 "s_register_operand" "r,r")
9126 (match_operand:SI 5 "shift_amount_operand" "M,r")])
9127 (match_operand:SI 2 "s_register_operand" "r,r")])
9128 (const_int 0)))
9129 (clobber (match_scratch:SI 0 "=r,r"))]
9130 "TARGET_32BIT"
9131 "%i1s%?\\t%0, %2, %4%S3"
9132 [(set_attr "conds" "set")
9133 (set_attr "shift" "4")
9134 (set_attr "arch" "32,a")
9135 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9136
9137 (define_insn "*sub_shiftsi"
9138 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9139 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9140 (match_operator:SI 2 "shift_operator"
9141 [(match_operand:SI 3 "s_register_operand" "r,r")
9142 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9143 "TARGET_32BIT"
9144 "sub%?\\t%0, %1, %3%S2"
9145 [(set_attr "predicable" "yes")
9146 (set_attr "predicable_short_it" "no")
9147 (set_attr "shift" "3")
9148 (set_attr "arch" "32,a")
9149 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
9150
9151 (define_insn "*sub_shiftsi_compare0"
9152 [(set (reg:CC_NOOV CC_REGNUM)
9153 (compare:CC_NOOV
9154 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
9155 (match_operator:SI 2 "shift_operator"
9156 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9157 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
9158 (const_int 0)))
9159 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9160 (minus:SI (match_dup 1)
9161 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9162 "TARGET_32BIT"
9163 "subs%?\\t%0, %1, %3%S2"
9164 [(set_attr "conds" "set")
9165 (set_attr "shift" "3")
9166 (set_attr "arch" "32,a,a")
9167 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9168
9169 (define_insn "*sub_shiftsi_compare0_scratch"
9170 [(set (reg:CC_NOOV CC_REGNUM)
9171 (compare:CC_NOOV
9172 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
9173 (match_operator:SI 2 "shift_operator"
9174 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9175 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
9176 (const_int 0)))
9177 (clobber (match_scratch:SI 0 "=r,r,r"))]
9178 "TARGET_32BIT"
9179 "subs%?\\t%0, %1, %3%S2"
9180 [(set_attr "conds" "set")
9181 (set_attr "shift" "3")
9182 (set_attr "arch" "32,a,a")
9183 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
9184 \f
9185
9186 (define_insn_and_split "*and_scc"
9187 [(set (match_operand:SI 0 "s_register_operand" "=r")
9188 (and:SI (match_operator:SI 1 "arm_comparison_operator"
9189 [(match_operand 2 "cc_register" "") (const_int 0)])
9190 (match_operand:SI 3 "s_register_operand" "r")))]
9191 "TARGET_ARM"
9192 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
9193 "&& reload_completed"
9194 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
9195 (cond_exec (match_dup 4) (set (match_dup 0)
9196 (and:SI (match_dup 3) (const_int 1))))]
9197 {
9198 machine_mode mode = GET_MODE (operands[2]);
9199 enum rtx_code rc = GET_CODE (operands[1]);
9200
9201 /* Note that operands[4] is the same as operands[1],
9202 but with VOIDmode as the result. */
9203 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9204 if (mode == CCFPmode || mode == CCFPEmode)
9205 rc = reverse_condition_maybe_unordered (rc);
9206 else
9207 rc = reverse_condition (rc);
9208 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9209 }
9210 [(set_attr "conds" "use")
9211 (set_attr "type" "multiple")
9212 (set_attr "length" "8")]
9213 )
9214
9215 (define_insn_and_split "*ior_scc"
9216 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9217 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
9218 [(match_operand 2 "cc_register" "") (const_int 0)])
9219 (match_operand:SI 3 "s_register_operand" "0,?r")))]
9220 "TARGET_ARM"
9221 "@
9222 orr%d1\\t%0, %3, #1
9223 #"
9224 "&& reload_completed
9225 && REGNO (operands [0]) != REGNO (operands[3])"
9226 ;; && which_alternative == 1
9227 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
9228 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
9229 (cond_exec (match_dup 4) (set (match_dup 0)
9230 (ior:SI (match_dup 3) (const_int 1))))]
9231 {
9232 machine_mode mode = GET_MODE (operands[2]);
9233 enum rtx_code rc = GET_CODE (operands[1]);
9234
9235 /* Note that operands[4] is the same as operands[1],
9236 but with VOIDmode as the result. */
9237 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9238 if (mode == CCFPmode || mode == CCFPEmode)
9239 rc = reverse_condition_maybe_unordered (rc);
9240 else
9241 rc = reverse_condition (rc);
9242 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
9243 }
9244 [(set_attr "conds" "use")
9245 (set_attr "length" "4,8")
9246 (set_attr "type" "logic_imm,multiple")]
9247 )
9248
9249 ; A series of splitters for the compare_scc pattern below. Note that
9250 ; order is important.
9251 (define_split
9252 [(set (match_operand:SI 0 "s_register_operand" "")
9253 (lt:SI (match_operand:SI 1 "s_register_operand" "")
9254 (const_int 0)))
9255 (clobber (reg:CC CC_REGNUM))]
9256 "TARGET_32BIT && reload_completed"
9257 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9258
9259 (define_split
9260 [(set (match_operand:SI 0 "s_register_operand" "")
9261 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9262 (const_int 0)))
9263 (clobber (reg:CC CC_REGNUM))]
9264 "TARGET_32BIT && reload_completed"
9265 [(set (match_dup 0) (not:SI (match_dup 1)))
9266 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9267
9268 (define_split
9269 [(set (match_operand:SI 0 "s_register_operand" "")
9270 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9271 (const_int 0)))
9272 (clobber (reg:CC CC_REGNUM))]
9273 "arm_arch5t && TARGET_32BIT"
9274 [(set (match_dup 0) (clz:SI (match_dup 1)))
9275 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9276 )
9277
9278 (define_split
9279 [(set (match_operand:SI 0 "s_register_operand" "")
9280 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9281 (const_int 0)))
9282 (clobber (reg:CC CC_REGNUM))]
9283 "TARGET_32BIT && reload_completed"
9284 [(parallel
9285 [(set (reg:CC CC_REGNUM)
9286 (compare:CC (const_int 1) (match_dup 1)))
9287 (set (match_dup 0)
9288 (minus:SI (const_int 1) (match_dup 1)))])
9289 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
9290 (set (match_dup 0) (const_int 0)))])
9291
9292 (define_split
9293 [(set (match_operand:SI 0 "s_register_operand" "")
9294 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9295 (match_operand:SI 2 "const_int_operand" "")))
9296 (clobber (reg:CC CC_REGNUM))]
9297 "TARGET_32BIT && reload_completed"
9298 [(parallel
9299 [(set (reg:CC CC_REGNUM)
9300 (compare:CC (match_dup 1) (match_dup 2)))
9301 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9302 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9303 (set (match_dup 0) (const_int 1)))]
9304 {
9305 operands[3] = GEN_INT (-INTVAL (operands[2]));
9306 })
9307
9308 (define_split
9309 [(set (match_operand:SI 0 "s_register_operand" "")
9310 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9311 (match_operand:SI 2 "arm_add_operand" "")))
9312 (clobber (reg:CC CC_REGNUM))]
9313 "TARGET_32BIT && reload_completed"
9314 [(parallel
9315 [(set (reg:CC_NOOV CC_REGNUM)
9316 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9317 (const_int 0)))
9318 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9319 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9320 (set (match_dup 0) (const_int 1)))])
9321
9322 (define_insn_and_split "*compare_scc"
9323 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9324 (match_operator:SI 1 "arm_comparison_operator"
9325 [(match_operand:SI 2 "s_register_operand" "r,r")
9326 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9327 (clobber (reg:CC CC_REGNUM))]
9328 "TARGET_32BIT"
9329 "#"
9330 "&& reload_completed"
9331 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9332 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9333 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9334 {
9335 rtx tmp1;
9336 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9337 operands[2], operands[3]);
9338 enum rtx_code rc = GET_CODE (operands[1]);
9339
9340 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
9341
9342 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9343 if (mode == CCFPmode || mode == CCFPEmode)
9344 rc = reverse_condition_maybe_unordered (rc);
9345 else
9346 rc = reverse_condition (rc);
9347 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9348 }
9349 [(set_attr "type" "multiple")]
9350 )
9351
9352 ;; Attempt to improve the sequence generated by the compare_scc splitters
9353 ;; not to use conditional execution.
9354
9355 ;; Rd = (eq (reg1) (const_int0)) // ARMv5
9356 ;; clz Rd, reg1
9357 ;; lsr Rd, Rd, #5
9358 (define_peephole2
9359 [(set (reg:CC CC_REGNUM)
9360 (compare:CC (match_operand:SI 1 "register_operand" "")
9361 (const_int 0)))
9362 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9363 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9364 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9365 (set (match_dup 0) (const_int 1)))]
9366 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9367 [(set (match_dup 0) (clz:SI (match_dup 1)))
9368 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9369 )
9370
9371 ;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9372 ;; negs Rd, reg1
9373 ;; adc Rd, Rd, reg1
9374 (define_peephole2
9375 [(set (reg:CC CC_REGNUM)
9376 (compare:CC (match_operand:SI 1 "register_operand" "")
9377 (const_int 0)))
9378 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9379 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9380 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9381 (set (match_dup 0) (const_int 1)))
9382 (match_scratch:SI 2 "r")]
9383 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9384 [(parallel
9385 [(set (reg:CC CC_REGNUM)
9386 (compare:CC (const_int 0) (match_dup 1)))
9387 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9388 (set (match_dup 0)
9389 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9390 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9391 )
9392
9393 ;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
9394 ;; sub Rd, Reg1, reg2
9395 ;; clz Rd, Rd
9396 ;; lsr Rd, Rd, #5
9397 (define_peephole2
9398 [(set (reg:CC CC_REGNUM)
9399 (compare:CC (match_operand:SI 1 "register_operand" "")
9400 (match_operand:SI 2 "arm_rhs_operand" "")))
9401 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9402 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9403 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9404 (set (match_dup 0) (const_int 1)))]
9405 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
9406 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
9407 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9408 (set (match_dup 0) (clz:SI (match_dup 0)))
9409 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9410 )
9411
9412
9413 ;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
9414 ;; sub T1, Reg1, reg2
9415 ;; negs Rd, T1
9416 ;; adc Rd, Rd, T1
9417 (define_peephole2
9418 [(set (reg:CC CC_REGNUM)
9419 (compare:CC (match_operand:SI 1 "register_operand" "")
9420 (match_operand:SI 2 "arm_rhs_operand" "")))
9421 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9422 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9423 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9424 (set (match_dup 0) (const_int 1)))
9425 (match_scratch:SI 3 "r")]
9426 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9427 [(set (match_dup 3) (match_dup 4))
9428 (parallel
9429 [(set (reg:CC CC_REGNUM)
9430 (compare:CC (const_int 0) (match_dup 3)))
9431 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
9432 (set (match_dup 0)
9433 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9434 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9435 "
9436 if (CONST_INT_P (operands[2]))
9437 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9438 else
9439 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9440 ")
9441
9442 (define_insn "*cond_move"
9443 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9444 (if_then_else:SI (match_operator 3 "equality_operator"
9445 [(match_operator 4 "arm_comparison_operator"
9446 [(match_operand 5 "cc_register" "") (const_int 0)])
9447 (const_int 0)])
9448 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9449 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9450 "TARGET_ARM"
9451 "*
9452 if (GET_CODE (operands[3]) == NE)
9453 {
9454 if (which_alternative != 1)
9455 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9456 if (which_alternative != 0)
9457 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9458 return \"\";
9459 }
9460 if (which_alternative != 0)
9461 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9462 if (which_alternative != 1)
9463 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9464 return \"\";
9465 "
9466 [(set_attr "conds" "use")
9467 (set_attr_alternative "type"
9468 [(if_then_else (match_operand 2 "const_int_operand" "")
9469 (const_string "mov_imm")
9470 (const_string "mov_reg"))
9471 (if_then_else (match_operand 1 "const_int_operand" "")
9472 (const_string "mov_imm")
9473 (const_string "mov_reg"))
9474 (const_string "multiple")])
9475 (set_attr "length" "4,4,8")]
9476 )
9477
9478 (define_insn "*cond_arith"
9479 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9480 (match_operator:SI 5 "shiftable_operator"
9481 [(match_operator:SI 4 "arm_comparison_operator"
9482 [(match_operand:SI 2 "s_register_operand" "r,r")
9483 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9484 (match_operand:SI 1 "s_register_operand" "0,?r")]))
9485 (clobber (reg:CC CC_REGNUM))]
9486 "TARGET_ARM"
9487 "*
9488 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9489 return \"%i5\\t%0, %1, %2, lsr #31\";
9490
9491 output_asm_insn (\"cmp\\t%2, %3\", operands);
9492 if (GET_CODE (operands[5]) == AND)
9493 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9494 else if (GET_CODE (operands[5]) == MINUS)
9495 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9496 else if (which_alternative != 0)
9497 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9498 return \"%i5%d4\\t%0, %1, #1\";
9499 "
9500 [(set_attr "conds" "clob")
9501 (set_attr "length" "12")
9502 (set_attr "type" "multiple")]
9503 )
9504
9505 (define_insn "*cond_sub"
9506 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9507 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9508 (match_operator:SI 4 "arm_comparison_operator"
9509 [(match_operand:SI 2 "s_register_operand" "r,r")
9510 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9511 (clobber (reg:CC CC_REGNUM))]
9512 "TARGET_ARM"
9513 "*
9514 output_asm_insn (\"cmp\\t%2, %3\", operands);
9515 if (which_alternative != 0)
9516 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9517 return \"sub%d4\\t%0, %1, #1\";
9518 "
9519 [(set_attr "conds" "clob")
9520 (set_attr "length" "8,12")
9521 (set_attr "type" "multiple")]
9522 )
9523
9524 (define_insn "*cmp_ite0"
9525 [(set (match_operand 6 "dominant_cc_register" "")
9526 (compare
9527 (if_then_else:SI
9528 (match_operator 4 "arm_comparison_operator"
9529 [(match_operand:SI 0 "s_register_operand"
9530 "l,l,l,r,r,r,r,r,r")
9531 (match_operand:SI 1 "arm_add_operand"
9532 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9533 (match_operator:SI 5 "arm_comparison_operator"
9534 [(match_operand:SI 2 "s_register_operand"
9535 "l,r,r,l,l,r,r,r,r")
9536 (match_operand:SI 3 "arm_add_operand"
9537 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9538 (const_int 0))
9539 (const_int 0)))]
9540 "TARGET_32BIT"
9541 "*
9542 {
9543 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9544 {
9545 {\"cmp%d5\\t%0, %1\",
9546 \"cmp%d4\\t%2, %3\"},
9547 {\"cmn%d5\\t%0, #%n1\",
9548 \"cmp%d4\\t%2, %3\"},
9549 {\"cmp%d5\\t%0, %1\",
9550 \"cmn%d4\\t%2, #%n3\"},
9551 {\"cmn%d5\\t%0, #%n1\",
9552 \"cmn%d4\\t%2, #%n3\"}
9553 };
9554 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9555 {
9556 {\"cmp\\t%2, %3\",
9557 \"cmp\\t%0, %1\"},
9558 {\"cmp\\t%2, %3\",
9559 \"cmn\\t%0, #%n1\"},
9560 {\"cmn\\t%2, #%n3\",
9561 \"cmp\\t%0, %1\"},
9562 {\"cmn\\t%2, #%n3\",
9563 \"cmn\\t%0, #%n1\"}
9564 };
9565 static const char * const ite[2] =
9566 {
9567 \"it\\t%d5\",
9568 \"it\\t%d4\"
9569 };
9570 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9571 CMP_CMP, CMN_CMP, CMP_CMP,
9572 CMN_CMP, CMP_CMN, CMN_CMN};
9573 int swap =
9574 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9575
9576 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9577 if (TARGET_THUMB2) {
9578 output_asm_insn (ite[swap], operands);
9579 }
9580 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9581 return \"\";
9582 }"
9583 [(set_attr "conds" "set")
9584 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9585 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9586 (set_attr "type" "multiple")
9587 (set_attr_alternative "length"
9588 [(const_int 6)
9589 (const_int 8)
9590 (const_int 8)
9591 (const_int 8)
9592 (const_int 8)
9593 (if_then_else (eq_attr "is_thumb" "no")
9594 (const_int 8)
9595 (const_int 10))
9596 (if_then_else (eq_attr "is_thumb" "no")
9597 (const_int 8)
9598 (const_int 10))
9599 (if_then_else (eq_attr "is_thumb" "no")
9600 (const_int 8)
9601 (const_int 10))
9602 (if_then_else (eq_attr "is_thumb" "no")
9603 (const_int 8)
9604 (const_int 10))])]
9605 )
9606
9607 (define_insn "*cmp_ite1"
9608 [(set (match_operand 6 "dominant_cc_register" "")
9609 (compare
9610 (if_then_else:SI
9611 (match_operator 4 "arm_comparison_operator"
9612 [(match_operand:SI 0 "s_register_operand"
9613 "l,l,l,r,r,r,r,r,r")
9614 (match_operand:SI 1 "arm_add_operand"
9615 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9616 (match_operator:SI 5 "arm_comparison_operator"
9617 [(match_operand:SI 2 "s_register_operand"
9618 "l,r,r,l,l,r,r,r,r")
9619 (match_operand:SI 3 "arm_add_operand"
9620 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9621 (const_int 1))
9622 (const_int 0)))]
9623 "TARGET_32BIT"
9624 "*
9625 {
9626 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9627 {
9628 {\"cmp\\t%0, %1\",
9629 \"cmp\\t%2, %3\"},
9630 {\"cmn\\t%0, #%n1\",
9631 \"cmp\\t%2, %3\"},
9632 {\"cmp\\t%0, %1\",
9633 \"cmn\\t%2, #%n3\"},
9634 {\"cmn\\t%0, #%n1\",
9635 \"cmn\\t%2, #%n3\"}
9636 };
9637 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9638 {
9639 {\"cmp%d4\\t%2, %3\",
9640 \"cmp%D5\\t%0, %1\"},
9641 {\"cmp%d4\\t%2, %3\",
9642 \"cmn%D5\\t%0, #%n1\"},
9643 {\"cmn%d4\\t%2, #%n3\",
9644 \"cmp%D5\\t%0, %1\"},
9645 {\"cmn%d4\\t%2, #%n3\",
9646 \"cmn%D5\\t%0, #%n1\"}
9647 };
9648 static const char * const ite[2] =
9649 {
9650 \"it\\t%d4\",
9651 \"it\\t%D5\"
9652 };
9653 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9654 CMP_CMP, CMN_CMP, CMP_CMP,
9655 CMN_CMP, CMP_CMN, CMN_CMN};
9656 int swap =
9657 comparison_dominates_p (GET_CODE (operands[5]),
9658 reverse_condition (GET_CODE (operands[4])));
9659
9660 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9661 if (TARGET_THUMB2) {
9662 output_asm_insn (ite[swap], operands);
9663 }
9664 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9665 return \"\";
9666 }"
9667 [(set_attr "conds" "set")
9668 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9669 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9670 (set_attr_alternative "length"
9671 [(const_int 6)
9672 (const_int 8)
9673 (const_int 8)
9674 (const_int 8)
9675 (const_int 8)
9676 (if_then_else (eq_attr "is_thumb" "no")
9677 (const_int 8)
9678 (const_int 10))
9679 (if_then_else (eq_attr "is_thumb" "no")
9680 (const_int 8)
9681 (const_int 10))
9682 (if_then_else (eq_attr "is_thumb" "no")
9683 (const_int 8)
9684 (const_int 10))
9685 (if_then_else (eq_attr "is_thumb" "no")
9686 (const_int 8)
9687 (const_int 10))])
9688 (set_attr "type" "multiple")]
9689 )
9690
9691 (define_insn "*cmp_and"
9692 [(set (match_operand 6 "dominant_cc_register" "")
9693 (compare
9694 (and:SI
9695 (match_operator 4 "arm_comparison_operator"
9696 [(match_operand:SI 0 "s_register_operand"
9697 "l,l,l,r,r,r,r,r,r")
9698 (match_operand:SI 1 "arm_add_operand"
9699 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9700 (match_operator:SI 5 "arm_comparison_operator"
9701 [(match_operand:SI 2 "s_register_operand"
9702 "l,r,r,l,l,r,r,r,r")
9703 (match_operand:SI 3 "arm_add_operand"
9704 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9705 (const_int 0)))]
9706 "TARGET_32BIT"
9707 "*
9708 {
9709 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9710 {
9711 {\"cmp%d5\\t%0, %1\",
9712 \"cmp%d4\\t%2, %3\"},
9713 {\"cmn%d5\\t%0, #%n1\",
9714 \"cmp%d4\\t%2, %3\"},
9715 {\"cmp%d5\\t%0, %1\",
9716 \"cmn%d4\\t%2, #%n3\"},
9717 {\"cmn%d5\\t%0, #%n1\",
9718 \"cmn%d4\\t%2, #%n3\"}
9719 };
9720 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9721 {
9722 {\"cmp\\t%2, %3\",
9723 \"cmp\\t%0, %1\"},
9724 {\"cmp\\t%2, %3\",
9725 \"cmn\\t%0, #%n1\"},
9726 {\"cmn\\t%2, #%n3\",
9727 \"cmp\\t%0, %1\"},
9728 {\"cmn\\t%2, #%n3\",
9729 \"cmn\\t%0, #%n1\"}
9730 };
9731 static const char *const ite[2] =
9732 {
9733 \"it\\t%d5\",
9734 \"it\\t%d4\"
9735 };
9736 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9737 CMP_CMP, CMN_CMP, CMP_CMP,
9738 CMN_CMP, CMP_CMN, CMN_CMN};
9739 int swap =
9740 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9741
9742 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9743 if (TARGET_THUMB2) {
9744 output_asm_insn (ite[swap], operands);
9745 }
9746 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9747 return \"\";
9748 }"
9749 [(set_attr "conds" "set")
9750 (set_attr "predicable" "no")
9751 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9752 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9753 (set_attr_alternative "length"
9754 [(const_int 6)
9755 (const_int 8)
9756 (const_int 8)
9757 (const_int 8)
9758 (const_int 8)
9759 (if_then_else (eq_attr "is_thumb" "no")
9760 (const_int 8)
9761 (const_int 10))
9762 (if_then_else (eq_attr "is_thumb" "no")
9763 (const_int 8)
9764 (const_int 10))
9765 (if_then_else (eq_attr "is_thumb" "no")
9766 (const_int 8)
9767 (const_int 10))
9768 (if_then_else (eq_attr "is_thumb" "no")
9769 (const_int 8)
9770 (const_int 10))])
9771 (set_attr "type" "multiple")]
9772 )
9773
9774 (define_insn "*cmp_ior"
9775 [(set (match_operand 6 "dominant_cc_register" "")
9776 (compare
9777 (ior:SI
9778 (match_operator 4 "arm_comparison_operator"
9779 [(match_operand:SI 0 "s_register_operand"
9780 "l,l,l,r,r,r,r,r,r")
9781 (match_operand:SI 1 "arm_add_operand"
9782 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9783 (match_operator:SI 5 "arm_comparison_operator"
9784 [(match_operand:SI 2 "s_register_operand"
9785 "l,r,r,l,l,r,r,r,r")
9786 (match_operand:SI 3 "arm_add_operand"
9787 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9788 (const_int 0)))]
9789 "TARGET_32BIT"
9790 "*
9791 {
9792 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9793 {
9794 {\"cmp\\t%0, %1\",
9795 \"cmp\\t%2, %3\"},
9796 {\"cmn\\t%0, #%n1\",
9797 \"cmp\\t%2, %3\"},
9798 {\"cmp\\t%0, %1\",
9799 \"cmn\\t%2, #%n3\"},
9800 {\"cmn\\t%0, #%n1\",
9801 \"cmn\\t%2, #%n3\"}
9802 };
9803 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9804 {
9805 {\"cmp%D4\\t%2, %3\",
9806 \"cmp%D5\\t%0, %1\"},
9807 {\"cmp%D4\\t%2, %3\",
9808 \"cmn%D5\\t%0, #%n1\"},
9809 {\"cmn%D4\\t%2, #%n3\",
9810 \"cmp%D5\\t%0, %1\"},
9811 {\"cmn%D4\\t%2, #%n3\",
9812 \"cmn%D5\\t%0, #%n1\"}
9813 };
9814 static const char *const ite[2] =
9815 {
9816 \"it\\t%D4\",
9817 \"it\\t%D5\"
9818 };
9819 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9820 CMP_CMP, CMN_CMP, CMP_CMP,
9821 CMN_CMP, CMP_CMN, CMN_CMN};
9822 int swap =
9823 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9824
9825 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9826 if (TARGET_THUMB2) {
9827 output_asm_insn (ite[swap], operands);
9828 }
9829 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9830 return \"\";
9831 }
9832 "
9833 [(set_attr "conds" "set")
9834 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9835 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9836 (set_attr_alternative "length"
9837 [(const_int 6)
9838 (const_int 8)
9839 (const_int 8)
9840 (const_int 8)
9841 (const_int 8)
9842 (if_then_else (eq_attr "is_thumb" "no")
9843 (const_int 8)
9844 (const_int 10))
9845 (if_then_else (eq_attr "is_thumb" "no")
9846 (const_int 8)
9847 (const_int 10))
9848 (if_then_else (eq_attr "is_thumb" "no")
9849 (const_int 8)
9850 (const_int 10))
9851 (if_then_else (eq_attr "is_thumb" "no")
9852 (const_int 8)
9853 (const_int 10))])
9854 (set_attr "type" "multiple")]
9855 )
9856
9857 (define_insn_and_split "*ior_scc_scc"
9858 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9859 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9860 [(match_operand:SI 1 "s_register_operand" "l,r")
9861 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9862 (match_operator:SI 6 "arm_comparison_operator"
9863 [(match_operand:SI 4 "s_register_operand" "l,r")
9864 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9865 (clobber (reg:CC CC_REGNUM))]
9866 "TARGET_32BIT
9867 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9868 != CCmode)"
9869 "#"
9870 "TARGET_32BIT && reload_completed"
9871 [(set (match_dup 7)
9872 (compare
9873 (ior:SI
9874 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9875 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9876 (const_int 0)))
9877 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9878 "operands[7]
9879 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9880 DOM_CC_X_OR_Y),
9881 CC_REGNUM);"
9882 [(set_attr "conds" "clob")
9883 (set_attr "enabled_for_short_it" "yes,no")
9884 (set_attr "length" "16")
9885 (set_attr "type" "multiple")]
9886 )
9887
9888 ; If the above pattern is followed by a CMP insn, then the compare is
9889 ; redundant, since we can rework the conditional instruction that follows.
9890 (define_insn_and_split "*ior_scc_scc_cmp"
9891 [(set (match_operand 0 "dominant_cc_register" "")
9892 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9893 [(match_operand:SI 1 "s_register_operand" "l,r")
9894 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9895 (match_operator:SI 6 "arm_comparison_operator"
9896 [(match_operand:SI 4 "s_register_operand" "l,r")
9897 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9898 (const_int 0)))
9899 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9900 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9901 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9902 "TARGET_32BIT"
9903 "#"
9904 "TARGET_32BIT && reload_completed"
9905 [(set (match_dup 0)
9906 (compare
9907 (ior:SI
9908 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9909 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9910 (const_int 0)))
9911 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9912 ""
9913 [(set_attr "conds" "set")
9914 (set_attr "enabled_for_short_it" "yes,no")
9915 (set_attr "length" "16")
9916 (set_attr "type" "multiple")]
9917 )
9918
9919 (define_insn_and_split "*and_scc_scc"
9920 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9921 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9922 [(match_operand:SI 1 "s_register_operand" "l,r")
9923 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9924 (match_operator:SI 6 "arm_comparison_operator"
9925 [(match_operand:SI 4 "s_register_operand" "l,r")
9926 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9927 (clobber (reg:CC CC_REGNUM))]
9928 "TARGET_32BIT
9929 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9930 != CCmode)"
9931 "#"
9932 "TARGET_32BIT && reload_completed
9933 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9934 != CCmode)"
9935 [(set (match_dup 7)
9936 (compare
9937 (and:SI
9938 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9939 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9940 (const_int 0)))
9941 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9942 "operands[7]
9943 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9944 DOM_CC_X_AND_Y),
9945 CC_REGNUM);"
9946 [(set_attr "conds" "clob")
9947 (set_attr "enabled_for_short_it" "yes,no")
9948 (set_attr "length" "16")
9949 (set_attr "type" "multiple")]
9950 )
9951
9952 ; If the above pattern is followed by a CMP insn, then the compare is
9953 ; redundant, since we can rework the conditional instruction that follows.
9954 (define_insn_and_split "*and_scc_scc_cmp"
9955 [(set (match_operand 0 "dominant_cc_register" "")
9956 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9957 [(match_operand:SI 1 "s_register_operand" "l,r")
9958 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9959 (match_operator:SI 6 "arm_comparison_operator"
9960 [(match_operand:SI 4 "s_register_operand" "l,r")
9961 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9962 (const_int 0)))
9963 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9964 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9965 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9966 "TARGET_32BIT"
9967 "#"
9968 "TARGET_32BIT && reload_completed"
9969 [(set (match_dup 0)
9970 (compare
9971 (and:SI
9972 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9973 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9974 (const_int 0)))
9975 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9976 ""
9977 [(set_attr "conds" "set")
9978 (set_attr "enabled_for_short_it" "yes,no")
9979 (set_attr "length" "16")
9980 (set_attr "type" "multiple")]
9981 )
9982
9983 ;; If there is no dominance in the comparison, then we can still save an
9984 ;; instruction in the AND case, since we can know that the second compare
9985 ;; need only zero the value if false (if true, then the value is already
9986 ;; correct).
9987 (define_insn_and_split "*and_scc_scc_nodom"
9988 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
9989 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9990 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9991 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9992 (match_operator:SI 6 "arm_comparison_operator"
9993 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9994 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9995 (clobber (reg:CC CC_REGNUM))]
9996 "TARGET_32BIT
9997 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9998 == CCmode)"
9999 "#"
10000 "TARGET_32BIT && reload_completed"
10001 [(parallel [(set (match_dup 0)
10002 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
10003 (clobber (reg:CC CC_REGNUM))])
10004 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
10005 (set (match_dup 0)
10006 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
10007 (match_dup 0)
10008 (const_int 0)))]
10009 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
10010 operands[4], operands[5]),
10011 CC_REGNUM);
10012 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
10013 operands[5]);"
10014 [(set_attr "conds" "clob")
10015 (set_attr "length" "20")
10016 (set_attr "type" "multiple")]
10017 )
10018
10019 (define_split
10020 [(set (reg:CC_NOOV CC_REGNUM)
10021 (compare:CC_NOOV (ior:SI
10022 (and:SI (match_operand:SI 0 "s_register_operand" "")
10023 (const_int 1))
10024 (match_operator:SI 1 "arm_comparison_operator"
10025 [(match_operand:SI 2 "s_register_operand" "")
10026 (match_operand:SI 3 "arm_add_operand" "")]))
10027 (const_int 0)))
10028 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10029 "TARGET_ARM"
10030 [(set (match_dup 4)
10031 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10032 (match_dup 0)))
10033 (set (reg:CC_NOOV CC_REGNUM)
10034 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10035 (const_int 0)))]
10036 "")
10037
10038 (define_split
10039 [(set (reg:CC_NOOV CC_REGNUM)
10040 (compare:CC_NOOV (ior:SI
10041 (match_operator:SI 1 "arm_comparison_operator"
10042 [(match_operand:SI 2 "s_register_operand" "")
10043 (match_operand:SI 3 "arm_add_operand" "")])
10044 (and:SI (match_operand:SI 0 "s_register_operand" "")
10045 (const_int 1)))
10046 (const_int 0)))
10047 (clobber (match_operand:SI 4 "s_register_operand" ""))]
10048 "TARGET_ARM"
10049 [(set (match_dup 4)
10050 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
10051 (match_dup 0)))
10052 (set (reg:CC_NOOV CC_REGNUM)
10053 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
10054 (const_int 0)))]
10055 "")
10056 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
10057
10058 (define_insn_and_split "*negscc"
10059 [(set (match_operand:SI 0 "s_register_operand" "=r")
10060 (neg:SI (match_operator 3 "arm_comparison_operator"
10061 [(match_operand:SI 1 "s_register_operand" "r")
10062 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
10063 (clobber (reg:CC CC_REGNUM))]
10064 "TARGET_ARM"
10065 "#"
10066 "&& reload_completed"
10067 [(const_int 0)]
10068 {
10069 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
10070
10071 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
10072 {
10073 /* Emit mov\\t%0, %1, asr #31 */
10074 emit_insn (gen_rtx_SET (operands[0],
10075 gen_rtx_ASHIFTRT (SImode,
10076 operands[1],
10077 GEN_INT (31))));
10078 DONE;
10079 }
10080 else if (GET_CODE (operands[3]) == NE)
10081 {
10082 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
10083 if (CONST_INT_P (operands[2]))
10084 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
10085 GEN_INT (- INTVAL (operands[2]))));
10086 else
10087 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
10088
10089 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10090 gen_rtx_NE (SImode,
10091 cc_reg,
10092 const0_rtx),
10093 gen_rtx_SET (operands[0],
10094 GEN_INT (~0))));
10095 DONE;
10096 }
10097 else
10098 {
10099 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
10100 emit_insn (gen_rtx_SET (cc_reg,
10101 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
10102 enum rtx_code rc = GET_CODE (operands[3]);
10103
10104 rc = reverse_condition (rc);
10105 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10106 gen_rtx_fmt_ee (rc,
10107 VOIDmode,
10108 cc_reg,
10109 const0_rtx),
10110 gen_rtx_SET (operands[0], const0_rtx)));
10111 rc = GET_CODE (operands[3]);
10112 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
10113 gen_rtx_fmt_ee (rc,
10114 VOIDmode,
10115 cc_reg,
10116 const0_rtx),
10117 gen_rtx_SET (operands[0],
10118 GEN_INT (~0))));
10119 DONE;
10120 }
10121 FAIL;
10122 }
10123 [(set_attr "conds" "clob")
10124 (set_attr "length" "12")
10125 (set_attr "type" "multiple")]
10126 )
10127
10128 (define_insn_and_split "movcond_addsi"
10129 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
10130 (if_then_else:SI
10131 (match_operator 5 "comparison_operator"
10132 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
10133 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
10134 (const_int 0)])
10135 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
10136 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
10137 (clobber (reg:CC CC_REGNUM))]
10138 "TARGET_32BIT"
10139 "#"
10140 "&& reload_completed"
10141 [(set (reg:CC_NOOV CC_REGNUM)
10142 (compare:CC_NOOV
10143 (plus:SI (match_dup 3)
10144 (match_dup 4))
10145 (const_int 0)))
10146 (set (match_dup 0) (match_dup 1))
10147 (cond_exec (match_dup 6)
10148 (set (match_dup 0) (match_dup 2)))]
10149 "
10150 {
10151 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
10152 operands[3], operands[4]);
10153 enum rtx_code rc = GET_CODE (operands[5]);
10154 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10155 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
10156 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
10157 rc = reverse_condition (rc);
10158 else
10159 std::swap (operands[1], operands[2]);
10160
10161 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10162 }
10163 "
10164 [(set_attr "conds" "clob")
10165 (set_attr "enabled_for_short_it" "no,yes,yes")
10166 (set_attr "type" "multiple")]
10167 )
10168
10169 (define_insn "movcond"
10170 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10171 (if_then_else:SI
10172 (match_operator 5 "arm_comparison_operator"
10173 [(match_operand:SI 3 "s_register_operand" "r,r,r")
10174 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
10175 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
10176 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
10177 (clobber (reg:CC CC_REGNUM))]
10178 "TARGET_ARM"
10179 "*
10180 if (GET_CODE (operands[5]) == LT
10181 && (operands[4] == const0_rtx))
10182 {
10183 if (which_alternative != 1 && REG_P (operands[1]))
10184 {
10185 if (operands[2] == const0_rtx)
10186 return \"and\\t%0, %1, %3, asr #31\";
10187 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
10188 }
10189 else if (which_alternative != 0 && REG_P (operands[2]))
10190 {
10191 if (operands[1] == const0_rtx)
10192 return \"bic\\t%0, %2, %3, asr #31\";
10193 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
10194 }
10195 /* The only case that falls through to here is when both ops 1 & 2
10196 are constants. */
10197 }
10198
10199 if (GET_CODE (operands[5]) == GE
10200 && (operands[4] == const0_rtx))
10201 {
10202 if (which_alternative != 1 && REG_P (operands[1]))
10203 {
10204 if (operands[2] == const0_rtx)
10205 return \"bic\\t%0, %1, %3, asr #31\";
10206 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
10207 }
10208 else if (which_alternative != 0 && REG_P (operands[2]))
10209 {
10210 if (operands[1] == const0_rtx)
10211 return \"and\\t%0, %2, %3, asr #31\";
10212 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
10213 }
10214 /* The only case that falls through to here is when both ops 1 & 2
10215 are constants. */
10216 }
10217 if (CONST_INT_P (operands[4])
10218 && !const_ok_for_arm (INTVAL (operands[4])))
10219 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
10220 else
10221 output_asm_insn (\"cmp\\t%3, %4\", operands);
10222 if (which_alternative != 0)
10223 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
10224 if (which_alternative != 1)
10225 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
10226 return \"\";
10227 "
10228 [(set_attr "conds" "clob")
10229 (set_attr "length" "8,8,12")
10230 (set_attr "type" "multiple")]
10231 )
10232
10233 ;; ??? The patterns below need checking for Thumb-2 usefulness.
10234
10235 (define_insn "*ifcompare_plus_move"
10236 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10237 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10238 [(match_operand:SI 4 "s_register_operand" "r,r")
10239 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10240 (plus:SI
10241 (match_operand:SI 2 "s_register_operand" "r,r")
10242 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
10243 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
10244 (clobber (reg:CC CC_REGNUM))]
10245 "TARGET_ARM"
10246 "#"
10247 [(set_attr "conds" "clob")
10248 (set_attr "length" "8,12")
10249 (set_attr "type" "multiple")]
10250 )
10251
10252 (define_insn "*if_plus_move"
10253 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
10254 (if_then_else:SI
10255 (match_operator 4 "arm_comparison_operator"
10256 [(match_operand 5 "cc_register" "") (const_int 0)])
10257 (plus:SI
10258 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10259 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
10260 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
10261 "TARGET_ARM"
10262 "@
10263 add%d4\\t%0, %2, %3
10264 sub%d4\\t%0, %2, #%n3
10265 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
10266 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
10267 [(set_attr "conds" "use")
10268 (set_attr "length" "4,4,8,8")
10269 (set_attr_alternative "type"
10270 [(if_then_else (match_operand 3 "const_int_operand" "")
10271 (const_string "alu_imm" )
10272 (const_string "alu_sreg"))
10273 (const_string "alu_imm")
10274 (const_string "multiple")
10275 (const_string "multiple")])]
10276 )
10277
10278 (define_insn "*ifcompare_move_plus"
10279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10280 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10281 [(match_operand:SI 4 "s_register_operand" "r,r")
10282 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10283 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10284 (plus:SI
10285 (match_operand:SI 2 "s_register_operand" "r,r")
10286 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
10287 (clobber (reg:CC CC_REGNUM))]
10288 "TARGET_ARM"
10289 "#"
10290 [(set_attr "conds" "clob")
10291 (set_attr "length" "8,12")
10292 (set_attr "type" "multiple")]
10293 )
10294
10295 (define_insn "*if_move_plus"
10296 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
10297 (if_then_else:SI
10298 (match_operator 4 "arm_comparison_operator"
10299 [(match_operand 5 "cc_register" "") (const_int 0)])
10300 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
10301 (plus:SI
10302 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10303 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
10304 "TARGET_ARM"
10305 "@
10306 add%D4\\t%0, %2, %3
10307 sub%D4\\t%0, %2, #%n3
10308 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
10309 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
10310 [(set_attr "conds" "use")
10311 (set_attr "length" "4,4,8,8")
10312 (set_attr_alternative "type"
10313 [(if_then_else (match_operand 3 "const_int_operand" "")
10314 (const_string "alu_imm" )
10315 (const_string "alu_sreg"))
10316 (const_string "alu_imm")
10317 (const_string "multiple")
10318 (const_string "multiple")])]
10319 )
10320
10321 (define_insn "*ifcompare_arith_arith"
10322 [(set (match_operand:SI 0 "s_register_operand" "=r")
10323 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
10324 [(match_operand:SI 5 "s_register_operand" "r")
10325 (match_operand:SI 6 "arm_add_operand" "rIL")])
10326 (match_operator:SI 8 "shiftable_operator"
10327 [(match_operand:SI 1 "s_register_operand" "r")
10328 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10329 (match_operator:SI 7 "shiftable_operator"
10330 [(match_operand:SI 3 "s_register_operand" "r")
10331 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
10332 (clobber (reg:CC CC_REGNUM))]
10333 "TARGET_ARM"
10334 "#"
10335 [(set_attr "conds" "clob")
10336 (set_attr "length" "12")
10337 (set_attr "type" "multiple")]
10338 )
10339
10340 (define_insn "*if_arith_arith"
10341 [(set (match_operand:SI 0 "s_register_operand" "=r")
10342 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
10343 [(match_operand 8 "cc_register" "") (const_int 0)])
10344 (match_operator:SI 6 "shiftable_operator"
10345 [(match_operand:SI 1 "s_register_operand" "r")
10346 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10347 (match_operator:SI 7 "shiftable_operator"
10348 [(match_operand:SI 3 "s_register_operand" "r")
10349 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
10350 "TARGET_ARM"
10351 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
10352 [(set_attr "conds" "use")
10353 (set_attr "length" "8")
10354 (set_attr "type" "multiple")]
10355 )
10356
10357 (define_insn "*ifcompare_arith_move"
10358 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10359 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10360 [(match_operand:SI 2 "s_register_operand" "r,r")
10361 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
10362 (match_operator:SI 7 "shiftable_operator"
10363 [(match_operand:SI 4 "s_register_operand" "r,r")
10364 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
10365 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
10366 (clobber (reg:CC CC_REGNUM))]
10367 "TARGET_ARM"
10368 "*
10369 /* If we have an operation where (op x 0) is the identity operation and
10370 the conditional operator is LT or GE and we are comparing against zero and
10371 everything is in registers then we can do this in two instructions. */
10372 if (operands[3] == const0_rtx
10373 && GET_CODE (operands[7]) != AND
10374 && REG_P (operands[5])
10375 && REG_P (operands[1])
10376 && REGNO (operands[1]) == REGNO (operands[4])
10377 && REGNO (operands[4]) != REGNO (operands[0]))
10378 {
10379 if (GET_CODE (operands[6]) == LT)
10380 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10381 else if (GET_CODE (operands[6]) == GE)
10382 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10383 }
10384 if (CONST_INT_P (operands[3])
10385 && !const_ok_for_arm (INTVAL (operands[3])))
10386 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
10387 else
10388 output_asm_insn (\"cmp\\t%2, %3\", operands);
10389 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
10390 if (which_alternative != 0)
10391 return \"mov%D6\\t%0, %1\";
10392 return \"\";
10393 "
10394 [(set_attr "conds" "clob")
10395 (set_attr "length" "8,12")
10396 (set_attr "type" "multiple")]
10397 )
10398
10399 (define_insn "*if_arith_move"
10400 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10401 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10402 [(match_operand 6 "cc_register" "") (const_int 0)])
10403 (match_operator:SI 5 "shiftable_operator"
10404 [(match_operand:SI 2 "s_register_operand" "r,r")
10405 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10406 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
10407 "TARGET_ARM"
10408 "@
10409 %I5%d4\\t%0, %2, %3
10410 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
10411 [(set_attr "conds" "use")
10412 (set_attr "length" "4,8")
10413 (set_attr_alternative "type"
10414 [(if_then_else (match_operand 3 "const_int_operand" "")
10415 (const_string "alu_shift_imm" )
10416 (const_string "alu_shift_reg"))
10417 (const_string "multiple")])]
10418 )
10419
10420 (define_insn "*ifcompare_move_arith"
10421 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10422 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10423 [(match_operand:SI 4 "s_register_operand" "r,r")
10424 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10425 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10426 (match_operator:SI 7 "shiftable_operator"
10427 [(match_operand:SI 2 "s_register_operand" "r,r")
10428 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
10429 (clobber (reg:CC CC_REGNUM))]
10430 "TARGET_ARM"
10431 "*
10432 /* If we have an operation where (op x 0) is the identity operation and
10433 the conditional operator is LT or GE and we are comparing against zero and
10434 everything is in registers then we can do this in two instructions */
10435 if (operands[5] == const0_rtx
10436 && GET_CODE (operands[7]) != AND
10437 && REG_P (operands[3])
10438 && REG_P (operands[1])
10439 && REGNO (operands[1]) == REGNO (operands[2])
10440 && REGNO (operands[2]) != REGNO (operands[0]))
10441 {
10442 if (GET_CODE (operands[6]) == GE)
10443 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10444 else if (GET_CODE (operands[6]) == LT)
10445 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10446 }
10447
10448 if (CONST_INT_P (operands[5])
10449 && !const_ok_for_arm (INTVAL (operands[5])))
10450 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10451 else
10452 output_asm_insn (\"cmp\\t%4, %5\", operands);
10453
10454 if (which_alternative != 0)
10455 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10456 return \"%I7%D6\\t%0, %2, %3\";
10457 "
10458 [(set_attr "conds" "clob")
10459 (set_attr "length" "8,12")
10460 (set_attr "type" "multiple")]
10461 )
10462
10463 (define_insn "*if_move_arith"
10464 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10465 (if_then_else:SI
10466 (match_operator 4 "arm_comparison_operator"
10467 [(match_operand 6 "cc_register" "") (const_int 0)])
10468 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10469 (match_operator:SI 5 "shiftable_operator"
10470 [(match_operand:SI 2 "s_register_operand" "r,r")
10471 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10472 "TARGET_ARM"
10473 "@
10474 %I5%D4\\t%0, %2, %3
10475 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10476 [(set_attr "conds" "use")
10477 (set_attr "length" "4,8")
10478 (set_attr_alternative "type"
10479 [(if_then_else (match_operand 3 "const_int_operand" "")
10480 (const_string "alu_shift_imm" )
10481 (const_string "alu_shift_reg"))
10482 (const_string "multiple")])]
10483 )
10484
10485 (define_insn "*ifcompare_move_not"
10486 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10487 (if_then_else:SI
10488 (match_operator 5 "arm_comparison_operator"
10489 [(match_operand:SI 3 "s_register_operand" "r,r")
10490 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10491 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10492 (not:SI
10493 (match_operand:SI 2 "s_register_operand" "r,r"))))
10494 (clobber (reg:CC CC_REGNUM))]
10495 "TARGET_ARM"
10496 "#"
10497 [(set_attr "conds" "clob")
10498 (set_attr "length" "8,12")
10499 (set_attr "type" "multiple")]
10500 )
10501
10502 (define_insn "*if_move_not"
10503 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10504 (if_then_else:SI
10505 (match_operator 4 "arm_comparison_operator"
10506 [(match_operand 3 "cc_register" "") (const_int 0)])
10507 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10508 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10509 "TARGET_ARM"
10510 "@
10511 mvn%D4\\t%0, %2
10512 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10513 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10514 [(set_attr "conds" "use")
10515 (set_attr "type" "mvn_reg")
10516 (set_attr "length" "4,8,8")
10517 (set_attr "type" "mvn_reg,multiple,multiple")]
10518 )
10519
10520 (define_insn "*ifcompare_not_move"
10521 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10522 (if_then_else:SI
10523 (match_operator 5 "arm_comparison_operator"
10524 [(match_operand:SI 3 "s_register_operand" "r,r")
10525 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10526 (not:SI
10527 (match_operand:SI 2 "s_register_operand" "r,r"))
10528 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10529 (clobber (reg:CC CC_REGNUM))]
10530 "TARGET_ARM"
10531 "#"
10532 [(set_attr "conds" "clob")
10533 (set_attr "length" "8,12")
10534 (set_attr "type" "multiple")]
10535 )
10536
10537 (define_insn "*if_not_move"
10538 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10539 (if_then_else:SI
10540 (match_operator 4 "arm_comparison_operator"
10541 [(match_operand 3 "cc_register" "") (const_int 0)])
10542 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10543 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10544 "TARGET_ARM"
10545 "@
10546 mvn%d4\\t%0, %2
10547 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10548 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10549 [(set_attr "conds" "use")
10550 (set_attr "type" "mvn_reg,multiple,multiple")
10551 (set_attr "length" "4,8,8")]
10552 )
10553
10554 (define_insn "*ifcompare_shift_move"
10555 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10556 (if_then_else:SI
10557 (match_operator 6 "arm_comparison_operator"
10558 [(match_operand:SI 4 "s_register_operand" "r,r")
10559 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10560 (match_operator:SI 7 "shift_operator"
10561 [(match_operand:SI 2 "s_register_operand" "r,r")
10562 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10563 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10564 (clobber (reg:CC CC_REGNUM))]
10565 "TARGET_ARM"
10566 "#"
10567 [(set_attr "conds" "clob")
10568 (set_attr "length" "8,12")
10569 (set_attr "type" "multiple")]
10570 )
10571
10572 (define_insn "*if_shift_move"
10573 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10574 (if_then_else:SI
10575 (match_operator 5 "arm_comparison_operator"
10576 [(match_operand 6 "cc_register" "") (const_int 0)])
10577 (match_operator:SI 4 "shift_operator"
10578 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10579 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10580 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10581 "TARGET_ARM"
10582 "@
10583 mov%d5\\t%0, %2%S4
10584 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10585 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10586 [(set_attr "conds" "use")
10587 (set_attr "shift" "2")
10588 (set_attr "length" "4,8,8")
10589 (set_attr_alternative "type"
10590 [(if_then_else (match_operand 3 "const_int_operand" "")
10591 (const_string "mov_shift" )
10592 (const_string "mov_shift_reg"))
10593 (const_string "multiple")
10594 (const_string "multiple")])]
10595 )
10596
10597 (define_insn "*ifcompare_move_shift"
10598 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10599 (if_then_else:SI
10600 (match_operator 6 "arm_comparison_operator"
10601 [(match_operand:SI 4 "s_register_operand" "r,r")
10602 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10603 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10604 (match_operator:SI 7 "shift_operator"
10605 [(match_operand:SI 2 "s_register_operand" "r,r")
10606 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10607 (clobber (reg:CC CC_REGNUM))]
10608 "TARGET_ARM"
10609 "#"
10610 [(set_attr "conds" "clob")
10611 (set_attr "length" "8,12")
10612 (set_attr "type" "multiple")]
10613 )
10614
10615 (define_insn "*if_move_shift"
10616 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10617 (if_then_else:SI
10618 (match_operator 5 "arm_comparison_operator"
10619 [(match_operand 6 "cc_register" "") (const_int 0)])
10620 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10621 (match_operator:SI 4 "shift_operator"
10622 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10623 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10624 "TARGET_ARM"
10625 "@
10626 mov%D5\\t%0, %2%S4
10627 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10628 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10629 [(set_attr "conds" "use")
10630 (set_attr "shift" "2")
10631 (set_attr "length" "4,8,8")
10632 (set_attr_alternative "type"
10633 [(if_then_else (match_operand 3 "const_int_operand" "")
10634 (const_string "mov_shift" )
10635 (const_string "mov_shift_reg"))
10636 (const_string "multiple")
10637 (const_string "multiple")])]
10638 )
10639
10640 (define_insn "*ifcompare_shift_shift"
10641 [(set (match_operand:SI 0 "s_register_operand" "=r")
10642 (if_then_else:SI
10643 (match_operator 7 "arm_comparison_operator"
10644 [(match_operand:SI 5 "s_register_operand" "r")
10645 (match_operand:SI 6 "arm_add_operand" "rIL")])
10646 (match_operator:SI 8 "shift_operator"
10647 [(match_operand:SI 1 "s_register_operand" "r")
10648 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10649 (match_operator:SI 9 "shift_operator"
10650 [(match_operand:SI 3 "s_register_operand" "r")
10651 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10652 (clobber (reg:CC CC_REGNUM))]
10653 "TARGET_ARM"
10654 "#"
10655 [(set_attr "conds" "clob")
10656 (set_attr "length" "12")
10657 (set_attr "type" "multiple")]
10658 )
10659
10660 (define_insn "*if_shift_shift"
10661 [(set (match_operand:SI 0 "s_register_operand" "=r")
10662 (if_then_else:SI
10663 (match_operator 5 "arm_comparison_operator"
10664 [(match_operand 8 "cc_register" "") (const_int 0)])
10665 (match_operator:SI 6 "shift_operator"
10666 [(match_operand:SI 1 "s_register_operand" "r")
10667 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10668 (match_operator:SI 7 "shift_operator"
10669 [(match_operand:SI 3 "s_register_operand" "r")
10670 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10671 "TARGET_ARM"
10672 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10673 [(set_attr "conds" "use")
10674 (set_attr "shift" "1")
10675 (set_attr "length" "8")
10676 (set (attr "type") (if_then_else
10677 (and (match_operand 2 "const_int_operand" "")
10678 (match_operand 4 "const_int_operand" ""))
10679 (const_string "mov_shift")
10680 (const_string "mov_shift_reg")))]
10681 )
10682
10683 (define_insn "*ifcompare_not_arith"
10684 [(set (match_operand:SI 0 "s_register_operand" "=r")
10685 (if_then_else:SI
10686 (match_operator 6 "arm_comparison_operator"
10687 [(match_operand:SI 4 "s_register_operand" "r")
10688 (match_operand:SI 5 "arm_add_operand" "rIL")])
10689 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10690 (match_operator:SI 7 "shiftable_operator"
10691 [(match_operand:SI 2 "s_register_operand" "r")
10692 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10693 (clobber (reg:CC CC_REGNUM))]
10694 "TARGET_ARM"
10695 "#"
10696 [(set_attr "conds" "clob")
10697 (set_attr "length" "12")
10698 (set_attr "type" "multiple")]
10699 )
10700
10701 (define_insn "*if_not_arith"
10702 [(set (match_operand:SI 0 "s_register_operand" "=r")
10703 (if_then_else:SI
10704 (match_operator 5 "arm_comparison_operator"
10705 [(match_operand 4 "cc_register" "") (const_int 0)])
10706 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10707 (match_operator:SI 6 "shiftable_operator"
10708 [(match_operand:SI 2 "s_register_operand" "r")
10709 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10710 "TARGET_ARM"
10711 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10712 [(set_attr "conds" "use")
10713 (set_attr "type" "mvn_reg")
10714 (set_attr "length" "8")]
10715 )
10716
10717 (define_insn "*ifcompare_arith_not"
10718 [(set (match_operand:SI 0 "s_register_operand" "=r")
10719 (if_then_else:SI
10720 (match_operator 6 "arm_comparison_operator"
10721 [(match_operand:SI 4 "s_register_operand" "r")
10722 (match_operand:SI 5 "arm_add_operand" "rIL")])
10723 (match_operator:SI 7 "shiftable_operator"
10724 [(match_operand:SI 2 "s_register_operand" "r")
10725 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10726 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10727 (clobber (reg:CC CC_REGNUM))]
10728 "TARGET_ARM"
10729 "#"
10730 [(set_attr "conds" "clob")
10731 (set_attr "length" "12")
10732 (set_attr "type" "multiple")]
10733 )
10734
10735 (define_insn "*if_arith_not"
10736 [(set (match_operand:SI 0 "s_register_operand" "=r")
10737 (if_then_else:SI
10738 (match_operator 5 "arm_comparison_operator"
10739 [(match_operand 4 "cc_register" "") (const_int 0)])
10740 (match_operator:SI 6 "shiftable_operator"
10741 [(match_operand:SI 2 "s_register_operand" "r")
10742 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10743 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10744 "TARGET_ARM"
10745 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10746 [(set_attr "conds" "use")
10747 (set_attr "type" "multiple")
10748 (set_attr "length" "8")]
10749 )
10750
10751 (define_insn "*ifcompare_neg_move"
10752 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10753 (if_then_else:SI
10754 (match_operator 5 "arm_comparison_operator"
10755 [(match_operand:SI 3 "s_register_operand" "r,r")
10756 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10757 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10758 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10759 (clobber (reg:CC CC_REGNUM))]
10760 "TARGET_ARM"
10761 "#"
10762 [(set_attr "conds" "clob")
10763 (set_attr "length" "8,12")
10764 (set_attr "type" "multiple")]
10765 )
10766
10767 (define_insn_and_split "*if_neg_move"
10768 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10769 (if_then_else:SI
10770 (match_operator 4 "arm_comparison_operator"
10771 [(match_operand 3 "cc_register" "") (const_int 0)])
10772 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10773 (match_operand:SI 1 "s_register_operand" "0,0")))]
10774 "TARGET_32BIT"
10775 "#"
10776 "&& reload_completed"
10777 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10778 (set (match_dup 0) (neg:SI (match_dup 2))))]
10779 ""
10780 [(set_attr "conds" "use")
10781 (set_attr "length" "4")
10782 (set_attr "arch" "t2,32")
10783 (set_attr "enabled_for_short_it" "yes,no")
10784 (set_attr "type" "logic_shift_imm")]
10785 )
10786
10787 (define_insn "*ifcompare_move_neg"
10788 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10789 (if_then_else:SI
10790 (match_operator 5 "arm_comparison_operator"
10791 [(match_operand:SI 3 "s_register_operand" "r,r")
10792 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10793 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10794 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10795 (clobber (reg:CC CC_REGNUM))]
10796 "TARGET_ARM"
10797 "#"
10798 [(set_attr "conds" "clob")
10799 (set_attr "length" "8,12")
10800 (set_attr "type" "multiple")]
10801 )
10802
10803 (define_insn_and_split "*if_move_neg"
10804 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10805 (if_then_else:SI
10806 (match_operator 4 "arm_comparison_operator"
10807 [(match_operand 3 "cc_register" "") (const_int 0)])
10808 (match_operand:SI 1 "s_register_operand" "0,0")
10809 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10810 "TARGET_32BIT"
10811 "#"
10812 "&& reload_completed"
10813 [(cond_exec (match_dup 5)
10814 (set (match_dup 0) (neg:SI (match_dup 2))))]
10815 {
10816 machine_mode mode = GET_MODE (operands[3]);
10817 rtx_code rc = GET_CODE (operands[4]);
10818
10819 if (mode == CCFPmode || mode == CCFPEmode)
10820 rc = reverse_condition_maybe_unordered (rc);
10821 else
10822 rc = reverse_condition (rc);
10823
10824 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10825 }
10826 [(set_attr "conds" "use")
10827 (set_attr "length" "4")
10828 (set_attr "arch" "t2,32")
10829 (set_attr "enabled_for_short_it" "yes,no")
10830 (set_attr "type" "logic_shift_imm")]
10831 )
10832
10833 (define_insn "*arith_adjacentmem"
10834 [(set (match_operand:SI 0 "s_register_operand" "=r")
10835 (match_operator:SI 1 "shiftable_operator"
10836 [(match_operand:SI 2 "memory_operand" "m")
10837 (match_operand:SI 3 "memory_operand" "m")]))
10838 (clobber (match_scratch:SI 4 "=r"))]
10839 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10840 "*
10841 {
10842 rtx ldm[3];
10843 rtx arith[4];
10844 rtx base_reg;
10845 HOST_WIDE_INT val1 = 0, val2 = 0;
10846
10847 if (REGNO (operands[0]) > REGNO (operands[4]))
10848 {
10849 ldm[1] = operands[4];
10850 ldm[2] = operands[0];
10851 }
10852 else
10853 {
10854 ldm[1] = operands[0];
10855 ldm[2] = operands[4];
10856 }
10857
10858 base_reg = XEXP (operands[2], 0);
10859
10860 if (!REG_P (base_reg))
10861 {
10862 val1 = INTVAL (XEXP (base_reg, 1));
10863 base_reg = XEXP (base_reg, 0);
10864 }
10865
10866 if (!REG_P (XEXP (operands[3], 0)))
10867 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10868
10869 arith[0] = operands[0];
10870 arith[3] = operands[1];
10871
10872 if (val1 < val2)
10873 {
10874 arith[1] = ldm[1];
10875 arith[2] = ldm[2];
10876 }
10877 else
10878 {
10879 arith[1] = ldm[2];
10880 arith[2] = ldm[1];
10881 }
10882
10883 ldm[0] = base_reg;
10884 if (val1 !=0 && val2 != 0)
10885 {
10886 rtx ops[3];
10887
10888 if (val1 == 4 || val2 == 4)
10889 /* Other val must be 8, since we know they are adjacent and neither
10890 is zero. */
10891 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
10892 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10893 {
10894 ldm[0] = ops[0] = operands[4];
10895 ops[1] = base_reg;
10896 ops[2] = GEN_INT (val1);
10897 output_add_immediate (ops);
10898 if (val1 < val2)
10899 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10900 else
10901 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10902 }
10903 else
10904 {
10905 /* Offset is out of range for a single add, so use two ldr. */
10906 ops[0] = ldm[1];
10907 ops[1] = base_reg;
10908 ops[2] = GEN_INT (val1);
10909 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10910 ops[0] = ldm[2];
10911 ops[2] = GEN_INT (val2);
10912 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10913 }
10914 }
10915 else if (val1 != 0)
10916 {
10917 if (val1 < val2)
10918 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10919 else
10920 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10921 }
10922 else
10923 {
10924 if (val1 < val2)
10925 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10926 else
10927 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10928 }
10929 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10930 return \"\";
10931 }"
10932 [(set_attr "length" "12")
10933 (set_attr "predicable" "yes")
10934 (set_attr "type" "load_4")]
10935 )
10936
10937 ; This pattern is never tried by combine, so do it as a peephole
10938
10939 (define_peephole2
10940 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10941 (match_operand:SI 1 "arm_general_register_operand" ""))
10942 (set (reg:CC CC_REGNUM)
10943 (compare:CC (match_dup 1) (const_int 0)))]
10944 "TARGET_ARM"
10945 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10946 (set (match_dup 0) (match_dup 1))])]
10947 ""
10948 )
10949
10950 (define_split
10951 [(set (match_operand:SI 0 "s_register_operand" "")
10952 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10953 (const_int 0))
10954 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10955 [(match_operand:SI 3 "s_register_operand" "")
10956 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10957 (clobber (match_operand:SI 5 "s_register_operand" ""))]
10958 "TARGET_ARM"
10959 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10960 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10961 (match_dup 5)))]
10962 ""
10963 )
10964
10965 ;; This split can be used because CC_Z mode implies that the following
10966 ;; branch will be an equality, or an unsigned inequality, so the sign
10967 ;; extension is not needed.
10968
10969 (define_split
10970 [(set (reg:CC_Z CC_REGNUM)
10971 (compare:CC_Z
10972 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10973 (const_int 24))
10974 (match_operand 1 "const_int_operand" "")))
10975 (clobber (match_scratch:SI 2 ""))]
10976 "TARGET_ARM
10977 && ((UINTVAL (operands[1]))
10978 == ((UINTVAL (operands[1])) >> 24) << 24)"
10979 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10980 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10981 "
10982 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10983 "
10984 )
10985 ;; ??? Check the patterns above for Thumb-2 usefulness
10986
10987 (define_expand "prologue"
10988 [(clobber (const_int 0))]
10989 "TARGET_EITHER"
10990 "if (TARGET_32BIT)
10991 arm_expand_prologue ();
10992 else
10993 thumb1_expand_prologue ();
10994 DONE;
10995 "
10996 )
10997
10998 (define_expand "epilogue"
10999 [(clobber (const_int 0))]
11000 "TARGET_EITHER"
11001 "
11002 if (crtl->calls_eh_return)
11003 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
11004 if (TARGET_THUMB1)
11005 {
11006 thumb1_expand_epilogue ();
11007 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
11008 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
11009 }
11010 else if (HAVE_return)
11011 {
11012 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
11013 no need for explicit testing again. */
11014 emit_jump_insn (gen_return ());
11015 }
11016 else if (TARGET_32BIT)
11017 {
11018 arm_expand_epilogue (true);
11019 }
11020 DONE;
11021 "
11022 )
11023
11024 ;; Note - although unspec_volatile's USE all hard registers,
11025 ;; USEs are ignored after relaod has completed. Thus we need
11026 ;; to add an unspec of the link register to ensure that flow
11027 ;; does not think that it is unused by the sibcall branch that
11028 ;; will replace the standard function epilogue.
11029 (define_expand "sibcall_epilogue"
11030 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
11031 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
11032 "TARGET_32BIT"
11033 "
11034 arm_expand_epilogue (false);
11035 DONE;
11036 "
11037 )
11038
11039 (define_expand "eh_epilogue"
11040 [(use (match_operand:SI 0 "register_operand" ""))
11041 (use (match_operand:SI 1 "register_operand" ""))
11042 (use (match_operand:SI 2 "register_operand" ""))]
11043 "TARGET_EITHER"
11044 "
11045 {
11046 cfun->machine->eh_epilogue_sp_ofs = operands[1];
11047 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
11048 {
11049 rtx ra = gen_rtx_REG (Pmode, 2);
11050
11051 emit_move_insn (ra, operands[2]);
11052 operands[2] = ra;
11053 }
11054 /* This is a hack -- we may have crystalized the function type too
11055 early. */
11056 cfun->machine->func_type = 0;
11057 }"
11058 )
11059
11060 ;; This split is only used during output to reduce the number of patterns
11061 ;; that need assembler instructions adding to them. We allowed the setting
11062 ;; of the conditions to be implicit during rtl generation so that
11063 ;; the conditional compare patterns would work. However this conflicts to
11064 ;; some extent with the conditional data operations, so we have to split them
11065 ;; up again here.
11066
11067 ;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
11068 ;; conditional execution sufficient?
11069
11070 (define_split
11071 [(set (match_operand:SI 0 "s_register_operand" "")
11072 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11073 [(match_operand 2 "" "") (match_operand 3 "" "")])
11074 (match_dup 0)
11075 (match_operand 4 "" "")))
11076 (clobber (reg:CC CC_REGNUM))]
11077 "TARGET_ARM && reload_completed"
11078 [(set (match_dup 5) (match_dup 6))
11079 (cond_exec (match_dup 7)
11080 (set (match_dup 0) (match_dup 4)))]
11081 "
11082 {
11083 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11084 operands[2], operands[3]);
11085 enum rtx_code rc = GET_CODE (operands[1]);
11086
11087 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
11088 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11089 if (mode == CCFPmode || mode == CCFPEmode)
11090 rc = reverse_condition_maybe_unordered (rc);
11091 else
11092 rc = reverse_condition (rc);
11093
11094 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
11095 }"
11096 )
11097
11098 (define_split
11099 [(set (match_operand:SI 0 "s_register_operand" "")
11100 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11101 [(match_operand 2 "" "") (match_operand 3 "" "")])
11102 (match_operand 4 "" "")
11103 (match_dup 0)))
11104 (clobber (reg:CC CC_REGNUM))]
11105 "TARGET_ARM && reload_completed"
11106 [(set (match_dup 5) (match_dup 6))
11107 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
11108 (set (match_dup 0) (match_dup 4)))]
11109 "
11110 {
11111 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11112 operands[2], operands[3]);
11113
11114 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
11115 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11116 }"
11117 )
11118
11119 (define_split
11120 [(set (match_operand:SI 0 "s_register_operand" "")
11121 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11122 [(match_operand 2 "" "") (match_operand 3 "" "")])
11123 (match_operand 4 "" "")
11124 (match_operand 5 "" "")))
11125 (clobber (reg:CC CC_REGNUM))]
11126 "TARGET_ARM && reload_completed"
11127 [(set (match_dup 6) (match_dup 7))
11128 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11129 (set (match_dup 0) (match_dup 4)))
11130 (cond_exec (match_dup 8)
11131 (set (match_dup 0) (match_dup 5)))]
11132 "
11133 {
11134 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11135 operands[2], operands[3]);
11136 enum rtx_code rc = GET_CODE (operands[1]);
11137
11138 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
11139 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11140 if (mode == CCFPmode || mode == CCFPEmode)
11141 rc = reverse_condition_maybe_unordered (rc);
11142 else
11143 rc = reverse_condition (rc);
11144
11145 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
11146 }"
11147 )
11148
11149 (define_split
11150 [(set (match_operand:SI 0 "s_register_operand" "")
11151 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
11152 [(match_operand:SI 2 "s_register_operand" "")
11153 (match_operand:SI 3 "arm_add_operand" "")])
11154 (match_operand:SI 4 "arm_rhs_operand" "")
11155 (not:SI
11156 (match_operand:SI 5 "s_register_operand" ""))))
11157 (clobber (reg:CC CC_REGNUM))]
11158 "TARGET_ARM && reload_completed"
11159 [(set (match_dup 6) (match_dup 7))
11160 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
11161 (set (match_dup 0) (match_dup 4)))
11162 (cond_exec (match_dup 8)
11163 (set (match_dup 0) (not:SI (match_dup 5))))]
11164 "
11165 {
11166 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
11167 operands[2], operands[3]);
11168 enum rtx_code rc = GET_CODE (operands[1]);
11169
11170 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
11171 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
11172 if (mode == CCFPmode || mode == CCFPEmode)
11173 rc = reverse_condition_maybe_unordered (rc);
11174 else
11175 rc = reverse_condition (rc);
11176
11177 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
11178 }"
11179 )
11180
11181 (define_insn "*cond_move_not"
11182 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
11183 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
11184 [(match_operand 3 "cc_register" "") (const_int 0)])
11185 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
11186 (not:SI
11187 (match_operand:SI 2 "s_register_operand" "r,r"))))]
11188 "TARGET_ARM"
11189 "@
11190 mvn%D4\\t%0, %2
11191 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
11192 [(set_attr "conds" "use")
11193 (set_attr "type" "mvn_reg,multiple")
11194 (set_attr "length" "4,8")]
11195 )
11196
11197 ;; The next two patterns occur when an AND operation is followed by a
11198 ;; scc insn sequence
11199
11200 (define_insn "*sign_extract_onebit"
11201 [(set (match_operand:SI 0 "s_register_operand" "=r")
11202 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11203 (const_int 1)
11204 (match_operand:SI 2 "const_int_operand" "n")))
11205 (clobber (reg:CC CC_REGNUM))]
11206 "TARGET_ARM"
11207 "*
11208 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11209 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
11210 return \"mvnne\\t%0, #0\";
11211 "
11212 [(set_attr "conds" "clob")
11213 (set_attr "length" "8")
11214 (set_attr "type" "multiple")]
11215 )
11216
11217 (define_insn "*not_signextract_onebit"
11218 [(set (match_operand:SI 0 "s_register_operand" "=r")
11219 (not:SI
11220 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
11221 (const_int 1)
11222 (match_operand:SI 2 "const_int_operand" "n"))))
11223 (clobber (reg:CC CC_REGNUM))]
11224 "TARGET_ARM"
11225 "*
11226 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
11227 output_asm_insn (\"tst\\t%1, %2\", operands);
11228 output_asm_insn (\"mvneq\\t%0, #0\", operands);
11229 return \"movne\\t%0, #0\";
11230 "
11231 [(set_attr "conds" "clob")
11232 (set_attr "length" "12")
11233 (set_attr "type" "multiple")]
11234 )
11235 ;; ??? The above patterns need auditing for Thumb-2
11236
11237 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
11238 ;; expressions. For simplicity, the first register is also in the unspec
11239 ;; part.
11240 ;; To avoid the usage of GNU extension, the length attribute is computed
11241 ;; in a C function arm_attr_length_push_multi.
11242 (define_insn "*push_multi"
11243 [(match_parallel 2 "multi_register_push"
11244 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
11245 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
11246 UNSPEC_PUSH_MULT))])]
11247 ""
11248 "*
11249 {
11250 int num_saves = XVECLEN (operands[2], 0);
11251
11252 /* For the StrongARM at least it is faster to
11253 use STR to store only a single register.
11254 In Thumb mode always use push, and the assembler will pick
11255 something appropriate. */
11256 if (num_saves == 1 && TARGET_ARM)
11257 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
11258 else
11259 {
11260 int i;
11261 char pattern[100];
11262
11263 if (TARGET_32BIT)
11264 strcpy (pattern, \"push%?\\t{%1\");
11265 else
11266 strcpy (pattern, \"push\\t{%1\");
11267
11268 for (i = 1; i < num_saves; i++)
11269 {
11270 strcat (pattern, \", %|\");
11271 strcat (pattern,
11272 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11273 }
11274
11275 strcat (pattern, \"}\");
11276 output_asm_insn (pattern, operands);
11277 }
11278
11279 return \"\";
11280 }"
11281 [(set_attr "type" "store_16")
11282 (set (attr "length")
11283 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
11284 )
11285
11286 (define_insn "stack_tie"
11287 [(set (mem:BLK (scratch))
11288 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11289 (match_operand:SI 1 "s_register_operand" "rk")]
11290 UNSPEC_PRLG_STK))]
11291 ""
11292 ""
11293 [(set_attr "length" "0")
11294 (set_attr "type" "block")]
11295 )
11296
11297 ;; Pop (as used in epilogue RTL)
11298 ;;
11299 (define_insn "*load_multiple_with_writeback"
11300 [(match_parallel 0 "load_multiple_operation"
11301 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11302 (plus:SI (match_dup 1)
11303 (match_operand:SI 2 "const_int_I_operand" "I")))
11304 (set (match_operand:SI 3 "s_register_operand" "=rk")
11305 (mem:SI (match_dup 1)))
11306 ])]
11307 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11308 "*
11309 {
11310 arm_output_multireg_pop (operands, /*return_pc=*/false,
11311 /*cond=*/const_true_rtx,
11312 /*reverse=*/false,
11313 /*update=*/true);
11314 return \"\";
11315 }
11316 "
11317 [(set_attr "type" "load_16")
11318 (set_attr "predicable" "yes")
11319 (set (attr "length")
11320 (symbol_ref "arm_attr_length_pop_multi (operands,
11321 /*return_pc=*/false,
11322 /*write_back_p=*/true)"))]
11323 )
11324
11325 ;; Pop with return (as used in epilogue RTL)
11326 ;;
11327 ;; This instruction is generated when the registers are popped at the end of
11328 ;; epilogue. Here, instead of popping the value into LR and then generating
11329 ;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11330 ;; with (return).
11331 (define_insn "*pop_multiple_with_writeback_and_return"
11332 [(match_parallel 0 "pop_multiple_return"
11333 [(return)
11334 (set (match_operand:SI 1 "s_register_operand" "+rk")
11335 (plus:SI (match_dup 1)
11336 (match_operand:SI 2 "const_int_I_operand" "I")))
11337 (set (match_operand:SI 3 "s_register_operand" "=rk")
11338 (mem:SI (match_dup 1)))
11339 ])]
11340 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11341 "*
11342 {
11343 arm_output_multireg_pop (operands, /*return_pc=*/true,
11344 /*cond=*/const_true_rtx,
11345 /*reverse=*/false,
11346 /*update=*/true);
11347 return \"\";
11348 }
11349 "
11350 [(set_attr "type" "load_16")
11351 (set_attr "predicable" "yes")
11352 (set (attr "length")
11353 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11354 /*write_back_p=*/true)"))]
11355 )
11356
11357 (define_insn "*pop_multiple_with_return"
11358 [(match_parallel 0 "pop_multiple_return"
11359 [(return)
11360 (set (match_operand:SI 2 "s_register_operand" "=rk")
11361 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11362 ])]
11363 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11364 "*
11365 {
11366 arm_output_multireg_pop (operands, /*return_pc=*/true,
11367 /*cond=*/const_true_rtx,
11368 /*reverse=*/false,
11369 /*update=*/false);
11370 return \"\";
11371 }
11372 "
11373 [(set_attr "type" "load_16")
11374 (set_attr "predicable" "yes")
11375 (set (attr "length")
11376 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11377 /*write_back_p=*/false)"))]
11378 )
11379
11380 ;; Load into PC and return
11381 (define_insn "*ldr_with_return"
11382 [(return)
11383 (set (reg:SI PC_REGNUM)
11384 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11385 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11386 "ldr%?\t%|pc, [%0], #4"
11387 [(set_attr "type" "load_4")
11388 (set_attr "predicable" "yes")]
11389 )
11390 ;; Pop for floating point registers (as used in epilogue RTL)
11391 (define_insn "*vfp_pop_multiple_with_writeback"
11392 [(match_parallel 0 "pop_multiple_fp"
11393 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11394 (plus:SI (match_dup 1)
11395 (match_operand:SI 2 "const_int_I_operand" "I")))
11396 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
11397 (mem:DF (match_dup 1)))])]
11398 "TARGET_32BIT && TARGET_HARD_FLOAT"
11399 "*
11400 {
11401 int num_regs = XVECLEN (operands[0], 0);
11402 char pattern[100];
11403 rtx op_list[2];
11404 strcpy (pattern, \"vldm\\t\");
11405 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11406 strcat (pattern, \"!, {\");
11407 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11408 strcat (pattern, \"%P0\");
11409 if ((num_regs - 1) > 1)
11410 {
11411 strcat (pattern, \"-%P1\");
11412 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11413 }
11414
11415 strcat (pattern, \"}\");
11416 output_asm_insn (pattern, op_list);
11417 return \"\";
11418 }
11419 "
11420 [(set_attr "type" "load_16")
11421 (set_attr "conds" "unconditional")
11422 (set_attr "predicable" "no")]
11423 )
11424
11425 ;; Special patterns for dealing with the constant pool
11426
11427 (define_insn "align_4"
11428 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
11429 "TARGET_EITHER"
11430 "*
11431 assemble_align (32);
11432 return \"\";
11433 "
11434 [(set_attr "type" "no_insn")]
11435 )
11436
11437 (define_insn "align_8"
11438 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
11439 "TARGET_EITHER"
11440 "*
11441 assemble_align (64);
11442 return \"\";
11443 "
11444 [(set_attr "type" "no_insn")]
11445 )
11446
11447 (define_insn "consttable_end"
11448 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
11449 "TARGET_EITHER"
11450 "*
11451 making_const_table = FALSE;
11452 return \"\";
11453 "
11454 [(set_attr "type" "no_insn")]
11455 )
11456
11457 (define_insn "consttable_1"
11458 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11459 "TARGET_EITHER"
11460 "*
11461 making_const_table = TRUE;
11462 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11463 assemble_zeros (3);
11464 return \"\";
11465 "
11466 [(set_attr "length" "4")
11467 (set_attr "type" "no_insn")]
11468 )
11469
11470 (define_insn "consttable_2"
11471 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11472 "TARGET_EITHER"
11473 "*
11474 {
11475 rtx x = operands[0];
11476 making_const_table = TRUE;
11477 switch (GET_MODE_CLASS (GET_MODE (x)))
11478 {
11479 case MODE_FLOAT:
11480 arm_emit_fp16_const (x);
11481 break;
11482 default:
11483 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11484 assemble_zeros (2);
11485 break;
11486 }
11487 return \"\";
11488 }"
11489 [(set_attr "length" "4")
11490 (set_attr "type" "no_insn")]
11491 )
11492
11493 (define_insn "consttable_4"
11494 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
11495 "TARGET_EITHER"
11496 "*
11497 {
11498 rtx x = operands[0];
11499 making_const_table = TRUE;
11500 scalar_float_mode float_mode;
11501 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
11502 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
11503 else
11504 {
11505 /* XXX: Sometimes gcc does something really dumb and ends up with
11506 a HIGH in a constant pool entry, usually because it's trying to
11507 load into a VFP register. We know this will always be used in
11508 combination with a LO_SUM which ignores the high bits, so just
11509 strip off the HIGH. */
11510 if (GET_CODE (x) == HIGH)
11511 x = XEXP (x, 0);
11512 assemble_integer (x, 4, BITS_PER_WORD, 1);
11513 mark_symbol_refs_as_used (x);
11514 }
11515 return \"\";
11516 }"
11517 [(set_attr "length" "4")
11518 (set_attr "type" "no_insn")]
11519 )
11520
11521 (define_insn "consttable_8"
11522 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11523 "TARGET_EITHER"
11524 "*
11525 {
11526 making_const_table = TRUE;
11527 scalar_float_mode float_mode;
11528 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11529 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11530 float_mode, BITS_PER_WORD);
11531 else
11532 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11533 return \"\";
11534 }"
11535 [(set_attr "length" "8")
11536 (set_attr "type" "no_insn")]
11537 )
11538
11539 (define_insn "consttable_16"
11540 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11541 "TARGET_EITHER"
11542 "*
11543 {
11544 making_const_table = TRUE;
11545 scalar_float_mode float_mode;
11546 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11547 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11548 float_mode, BITS_PER_WORD);
11549 else
11550 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11551 return \"\";
11552 }"
11553 [(set_attr "length" "16")
11554 (set_attr "type" "no_insn")]
11555 )
11556
11557 ;; V5 Instructions,
11558
11559 (define_insn "clzsi2"
11560 [(set (match_operand:SI 0 "s_register_operand" "=r")
11561 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11562 "TARGET_32BIT && arm_arch5t"
11563 "clz%?\\t%0, %1"
11564 [(set_attr "predicable" "yes")
11565 (set_attr "type" "clz")])
11566
11567 (define_insn "rbitsi2"
11568 [(set (match_operand:SI 0 "s_register_operand" "=r")
11569 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11570 "TARGET_32BIT && arm_arch_thumb2"
11571 "rbit%?\\t%0, %1"
11572 [(set_attr "predicable" "yes")
11573 (set_attr "type" "clz")])
11574
11575 ;; Keep this as a CTZ expression until after reload and then split
11576 ;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11577 ;; to fold with any other expression.
11578
11579 (define_insn_and_split "ctzsi2"
11580 [(set (match_operand:SI 0 "s_register_operand" "=r")
11581 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11582 "TARGET_32BIT && arm_arch_thumb2"
11583 "#"
11584 "&& reload_completed"
11585 [(const_int 0)]
11586 "
11587 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11588 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11589 DONE;
11590 ")
11591
11592 ;; V5E instructions.
11593
11594 (define_insn "prefetch"
11595 [(prefetch (match_operand:SI 0 "address_operand" "p")
11596 (match_operand:SI 1 "" "")
11597 (match_operand:SI 2 "" ""))]
11598 "TARGET_32BIT && arm_arch5te"
11599 "pld\\t%a0"
11600 [(set_attr "type" "load_4")]
11601 )
11602
11603 ;; General predication pattern
11604
11605 (define_cond_exec
11606 [(match_operator 0 "arm_comparison_operator"
11607 [(match_operand 1 "cc_register" "")
11608 (const_int 0)])]
11609 "TARGET_32BIT
11610 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
11611 ""
11612 [(set_attr "predicated" "yes")]
11613 )
11614
11615 (define_insn "force_register_use"
11616 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
11617 ""
11618 "%@ %0 needed"
11619 [(set_attr "length" "0")
11620 (set_attr "type" "no_insn")]
11621 )
11622
11623
11624 ;; Patterns for exception handling
11625
11626 (define_expand "eh_return"
11627 [(use (match_operand 0 "general_operand" ""))]
11628 "TARGET_EITHER"
11629 "
11630 {
11631 if (TARGET_32BIT)
11632 emit_insn (gen_arm_eh_return (operands[0]));
11633 else
11634 emit_insn (gen_thumb_eh_return (operands[0]));
11635 DONE;
11636 }"
11637 )
11638
11639 ;; We can't expand this before we know where the link register is stored.
11640 (define_insn_and_split "arm_eh_return"
11641 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11642 VUNSPEC_EH_RETURN)
11643 (clobber (match_scratch:SI 1 "=&r"))]
11644 "TARGET_ARM"
11645 "#"
11646 "&& reload_completed"
11647 [(const_int 0)]
11648 "
11649 {
11650 arm_set_return_address (operands[0], operands[1]);
11651 DONE;
11652 }"
11653 )
11654
11655 \f
11656 ;; TLS support
11657
11658 (define_insn "load_tp_hard"
11659 [(set (match_operand:SI 0 "register_operand" "=r")
11660 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11661 "TARGET_HARD_TP"
11662 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11663 [(set_attr "predicable" "yes")
11664 (set_attr "type" "mrs")]
11665 )
11666
11667 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11668 (define_insn "load_tp_soft"
11669 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11670 (clobber (reg:SI LR_REGNUM))
11671 (clobber (reg:SI IP_REGNUM))
11672 (clobber (reg:CC CC_REGNUM))]
11673 "TARGET_SOFT_TP"
11674 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11675 [(set_attr "conds" "clob")
11676 (set_attr "type" "branch")]
11677 )
11678
11679 ;; tls descriptor call
11680 (define_insn "tlscall"
11681 [(set (reg:SI R0_REGNUM)
11682 (unspec:SI [(reg:SI R0_REGNUM)
11683 (match_operand:SI 0 "" "X")
11684 (match_operand 1 "" "")] UNSPEC_TLS))
11685 (clobber (reg:SI R1_REGNUM))
11686 (clobber (reg:SI LR_REGNUM))
11687 (clobber (reg:SI CC_REGNUM))]
11688 "TARGET_GNU2_TLS"
11689 {
11690 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11691 INTVAL (operands[1]));
11692 return "bl\\t%c0(tlscall)";
11693 }
11694 [(set_attr "conds" "clob")
11695 (set_attr "length" "4")
11696 (set_attr "type" "branch")]
11697 )
11698
11699 ;; For thread pointer builtin
11700 (define_expand "get_thread_pointersi"
11701 [(match_operand:SI 0 "s_register_operand" "=r")]
11702 ""
11703 "
11704 {
11705 arm_load_tp (operands[0]);
11706 DONE;
11707 }")
11708
11709 ;;
11710
11711 ;; We only care about the lower 16 bits of the constant
11712 ;; being inserted into the upper 16 bits of the register.
11713 (define_insn "*arm_movtas_ze"
11714 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
11715 (const_int 16)
11716 (const_int 16))
11717 (match_operand:SI 1 "const_int_operand" ""))]
11718 "TARGET_HAVE_MOVT"
11719 "@
11720 movt%?\t%0, %L1
11721 movt\t%0, %L1"
11722 [(set_attr "arch" "32,v8mb")
11723 (set_attr "predicable" "yes")
11724 (set_attr "length" "4")
11725 (set_attr "type" "alu_sreg")]
11726 )
11727
11728 (define_insn "*arm_rev"
11729 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11730 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11731 "arm_arch6"
11732 "@
11733 rev\t%0, %1
11734 rev%?\t%0, %1
11735 rev%?\t%0, %1"
11736 [(set_attr "arch" "t1,t2,32")
11737 (set_attr "length" "2,2,4")
11738 (set_attr "predicable" "no,yes,yes")
11739 (set_attr "type" "rev")]
11740 )
11741
11742 (define_expand "arm_legacy_rev"
11743 [(set (match_operand:SI 2 "s_register_operand" "")
11744 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11745 (const_int 16))
11746 (match_dup 1)))
11747 (set (match_dup 2)
11748 (lshiftrt:SI (match_dup 2)
11749 (const_int 8)))
11750 (set (match_operand:SI 3 "s_register_operand" "")
11751 (rotatert:SI (match_dup 1)
11752 (const_int 8)))
11753 (set (match_dup 2)
11754 (and:SI (match_dup 2)
11755 (const_int -65281)))
11756 (set (match_operand:SI 0 "s_register_operand" "")
11757 (xor:SI (match_dup 3)
11758 (match_dup 2)))]
11759 "TARGET_32BIT"
11760 ""
11761 )
11762
11763 ;; Reuse temporaries to keep register pressure down.
11764 (define_expand "thumb_legacy_rev"
11765 [(set (match_operand:SI 2 "s_register_operand" "")
11766 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11767 (const_int 24)))
11768 (set (match_operand:SI 3 "s_register_operand" "")
11769 (lshiftrt:SI (match_dup 1)
11770 (const_int 24)))
11771 (set (match_dup 3)
11772 (ior:SI (match_dup 3)
11773 (match_dup 2)))
11774 (set (match_operand:SI 4 "s_register_operand" "")
11775 (const_int 16))
11776 (set (match_operand:SI 5 "s_register_operand" "")
11777 (rotatert:SI (match_dup 1)
11778 (match_dup 4)))
11779 (set (match_dup 2)
11780 (ashift:SI (match_dup 5)
11781 (const_int 24)))
11782 (set (match_dup 5)
11783 (lshiftrt:SI (match_dup 5)
11784 (const_int 24)))
11785 (set (match_dup 5)
11786 (ior:SI (match_dup 5)
11787 (match_dup 2)))
11788 (set (match_dup 5)
11789 (rotatert:SI (match_dup 5)
11790 (match_dup 4)))
11791 (set (match_operand:SI 0 "s_register_operand" "")
11792 (ior:SI (match_dup 5)
11793 (match_dup 3)))]
11794 "TARGET_THUMB"
11795 ""
11796 )
11797
11798 ;; ARM-specific expansion of signed mod by power of 2
11799 ;; using conditional negate.
11800 ;; For r0 % n where n is a power of 2 produce:
11801 ;; rsbs r1, r0, #0
11802 ;; and r0, r0, #(n - 1)
11803 ;; and r1, r1, #(n - 1)
11804 ;; rsbpl r0, r1, #0
11805
11806 (define_expand "modsi3"
11807 [(match_operand:SI 0 "register_operand" "")
11808 (match_operand:SI 1 "register_operand" "")
11809 (match_operand:SI 2 "const_int_operand" "")]
11810 "TARGET_32BIT"
11811 {
11812 HOST_WIDE_INT val = INTVAL (operands[2]);
11813
11814 if (val <= 0
11815 || exact_log2 (val) <= 0)
11816 FAIL;
11817
11818 rtx mask = GEN_INT (val - 1);
11819
11820 /* In the special case of x0 % 2 we can do the even shorter:
11821 cmp r0, #0
11822 and r0, r0, #1
11823 rsblt r0, r0, #0. */
11824
11825 if (val == 2)
11826 {
11827 rtx cc_reg = arm_gen_compare_reg (LT,
11828 operands[1], const0_rtx, NULL_RTX);
11829 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11830 rtx masked = gen_reg_rtx (SImode);
11831
11832 emit_insn (gen_andsi3 (masked, operands[1], mask));
11833 emit_move_insn (operands[0],
11834 gen_rtx_IF_THEN_ELSE (SImode, cond,
11835 gen_rtx_NEG (SImode,
11836 masked),
11837 masked));
11838 DONE;
11839 }
11840
11841 rtx neg_op = gen_reg_rtx (SImode);
11842 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11843 operands[1]));
11844
11845 /* Extract the condition register and mode. */
11846 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11847 rtx cc_reg = SET_DEST (cmp);
11848 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11849
11850 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11851
11852 rtx masked_neg = gen_reg_rtx (SImode);
11853 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11854
11855 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11856 during expand does not always work. Do an IF_THEN_ELSE instead. */
11857 emit_move_insn (operands[0],
11858 gen_rtx_IF_THEN_ELSE (SImode, cond,
11859 gen_rtx_NEG (SImode, masked_neg),
11860 operands[0]));
11861
11862
11863 DONE;
11864 }
11865 )
11866
11867 (define_expand "bswapsi2"
11868 [(set (match_operand:SI 0 "s_register_operand" "=r")
11869 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11870 "TARGET_EITHER && (arm_arch6 || !optimize_size)"
11871 "
11872 if (!arm_arch6)
11873 {
11874 rtx op2 = gen_reg_rtx (SImode);
11875 rtx op3 = gen_reg_rtx (SImode);
11876
11877 if (TARGET_THUMB)
11878 {
11879 rtx op4 = gen_reg_rtx (SImode);
11880 rtx op5 = gen_reg_rtx (SImode);
11881
11882 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11883 op2, op3, op4, op5));
11884 }
11885 else
11886 {
11887 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11888 op2, op3));
11889 }
11890
11891 DONE;
11892 }
11893 "
11894 )
11895
11896 ;; bswap16 patterns: use revsh and rev16 instructions for the signed
11897 ;; and unsigned variants, respectively. For rev16, expose
11898 ;; byte-swapping in the lower 16 bits only.
11899 (define_insn "*arm_revsh"
11900 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11901 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11902 "arm_arch6"
11903 "@
11904 revsh\t%0, %1
11905 revsh%?\t%0, %1
11906 revsh%?\t%0, %1"
11907 [(set_attr "arch" "t1,t2,32")
11908 (set_attr "length" "2,2,4")
11909 (set_attr "type" "rev")]
11910 )
11911
11912 (define_insn "*arm_rev16"
11913 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11914 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11915 "arm_arch6"
11916 "@
11917 rev16\t%0, %1
11918 rev16%?\t%0, %1
11919 rev16%?\t%0, %1"
11920 [(set_attr "arch" "t1,t2,32")
11921 (set_attr "length" "2,2,4")
11922 (set_attr "type" "rev")]
11923 )
11924
11925 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11926 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
11927 ;; each valid permutation.
11928
11929 (define_insn "arm_rev16si2"
11930 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11931 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11932 (const_int 8))
11933 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11934 (and:SI (lshiftrt:SI (match_dup 1)
11935 (const_int 8))
11936 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11937 "arm_arch6
11938 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11939 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11940 "rev16\\t%0, %1"
11941 [(set_attr "arch" "t1,t2,32")
11942 (set_attr "length" "2,2,4")
11943 (set_attr "type" "rev")]
11944 )
11945
11946 (define_insn "arm_rev16si2_alt"
11947 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11948 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11949 (const_int 8))
11950 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11951 (and:SI (ashift:SI (match_dup 1)
11952 (const_int 8))
11953 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11954 "arm_arch6
11955 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11956 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11957 "rev16\\t%0, %1"
11958 [(set_attr "arch" "t1,t2,32")
11959 (set_attr "length" "2,2,4")
11960 (set_attr "type" "rev")]
11961 )
11962
11963 (define_expand "bswaphi2"
11964 [(set (match_operand:HI 0 "s_register_operand" "=r")
11965 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11966 "arm_arch6"
11967 ""
11968 )
11969
11970 ;; Patterns for LDRD/STRD in Thumb2 mode
11971
11972 (define_insn "*thumb2_ldrd"
11973 [(set (match_operand:SI 0 "s_register_operand" "=r")
11974 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11975 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11976 (set (match_operand:SI 3 "s_register_operand" "=r")
11977 (mem:SI (plus:SI (match_dup 1)
11978 (match_operand:SI 4 "const_int_operand" ""))))]
11979 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11980 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11981 && (operands_ok_ldrd_strd (operands[0], operands[3],
11982 operands[1], INTVAL (operands[2]),
11983 false, true))"
11984 "ldrd%?\t%0, %3, [%1, %2]"
11985 [(set_attr "type" "load_8")
11986 (set_attr "predicable" "yes")])
11987
11988 (define_insn "*thumb2_ldrd_base"
11989 [(set (match_operand:SI 0 "s_register_operand" "=r")
11990 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11991 (set (match_operand:SI 2 "s_register_operand" "=r")
11992 (mem:SI (plus:SI (match_dup 1)
11993 (const_int 4))))]
11994 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11995 && (operands_ok_ldrd_strd (operands[0], operands[2],
11996 operands[1], 0, false, true))"
11997 "ldrd%?\t%0, %2, [%1]"
11998 [(set_attr "type" "load_8")
11999 (set_attr "predicable" "yes")])
12000
12001 (define_insn "*thumb2_ldrd_base_neg"
12002 [(set (match_operand:SI 0 "s_register_operand" "=r")
12003 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
12004 (const_int -4))))
12005 (set (match_operand:SI 2 "s_register_operand" "=r")
12006 (mem:SI (match_dup 1)))]
12007 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12008 && (operands_ok_ldrd_strd (operands[0], operands[2],
12009 operands[1], -4, false, true))"
12010 "ldrd%?\t%0, %2, [%1, #-4]"
12011 [(set_attr "type" "load_8")
12012 (set_attr "predicable" "yes")])
12013
12014 (define_insn "*thumb2_strd"
12015 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12016 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
12017 (match_operand:SI 2 "s_register_operand" "r"))
12018 (set (mem:SI (plus:SI (match_dup 0)
12019 (match_operand:SI 3 "const_int_operand" "")))
12020 (match_operand:SI 4 "s_register_operand" "r"))]
12021 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12022 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
12023 && (operands_ok_ldrd_strd (operands[2], operands[4],
12024 operands[0], INTVAL (operands[1]),
12025 false, false))"
12026 "strd%?\t%2, %4, [%0, %1]"
12027 [(set_attr "type" "store_8")
12028 (set_attr "predicable" "yes")])
12029
12030 (define_insn "*thumb2_strd_base"
12031 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
12032 (match_operand:SI 1 "s_register_operand" "r"))
12033 (set (mem:SI (plus:SI (match_dup 0)
12034 (const_int 4)))
12035 (match_operand:SI 2 "s_register_operand" "r"))]
12036 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12037 && (operands_ok_ldrd_strd (operands[1], operands[2],
12038 operands[0], 0, false, false))"
12039 "strd%?\t%1, %2, [%0]"
12040 [(set_attr "type" "store_8")
12041 (set_attr "predicable" "yes")])
12042
12043 (define_insn "*thumb2_strd_base_neg"
12044 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
12045 (const_int -4)))
12046 (match_operand:SI 1 "s_register_operand" "r"))
12047 (set (mem:SI (match_dup 0))
12048 (match_operand:SI 2 "s_register_operand" "r"))]
12049 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
12050 && (operands_ok_ldrd_strd (operands[1], operands[2],
12051 operands[0], -4, false, false))"
12052 "strd%?\t%1, %2, [%0, #-4]"
12053 [(set_attr "type" "store_8")
12054 (set_attr "predicable" "yes")])
12055
12056 ;; ARMv8 CRC32 instructions.
12057 (define_insn "<crc_variant>"
12058 [(set (match_operand:SI 0 "s_register_operand" "=r")
12059 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
12060 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
12061 CRC))]
12062 "TARGET_CRC32"
12063 "<crc_variant>\\t%0, %1, %2"
12064 [(set_attr "type" "crc")
12065 (set_attr "conds" "unconditional")]
12066 )
12067
12068 ;; Load the load/store double peephole optimizations.
12069 (include "ldrdstrd.md")
12070
12071 ;; Load the load/store multiple patterns
12072 (include "ldmstm.md")
12073
12074 ;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
12075 ;; large lists without explicit writeback generated for APCS_FRAME epilogue.
12076 ;; The operands are validated through the load_multiple_operation
12077 ;; match_parallel predicate rather than through constraints so enable it only
12078 ;; after reload.
12079 (define_insn "*load_multiple"
12080 [(match_parallel 0 "load_multiple_operation"
12081 [(set (match_operand:SI 2 "s_register_operand" "=rk")
12082 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
12083 ])]
12084 "TARGET_32BIT && reload_completed"
12085 "*
12086 {
12087 arm_output_multireg_pop (operands, /*return_pc=*/false,
12088 /*cond=*/const_true_rtx,
12089 /*reverse=*/false,
12090 /*update=*/false);
12091 return \"\";
12092 }
12093 "
12094 [(set_attr "predicable" "yes")]
12095 )
12096
12097 (define_expand "copysignsf3"
12098 [(match_operand:SF 0 "register_operand")
12099 (match_operand:SF 1 "register_operand")
12100 (match_operand:SF 2 "register_operand")]
12101 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
12102 "{
12103 emit_move_insn (operands[0], operands[2]);
12104 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
12105 GEN_INT (31), GEN_INT (0),
12106 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
12107 DONE;
12108 }"
12109 )
12110
12111 (define_expand "copysigndf3"
12112 [(match_operand:DF 0 "register_operand")
12113 (match_operand:DF 1 "register_operand")
12114 (match_operand:DF 2 "register_operand")]
12115 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
12116 "{
12117 rtx op0_low = gen_lowpart (SImode, operands[0]);
12118 rtx op0_high = gen_highpart (SImode, operands[0]);
12119 rtx op1_low = gen_lowpart (SImode, operands[1]);
12120 rtx op1_high = gen_highpart (SImode, operands[1]);
12121 rtx op2_high = gen_highpart (SImode, operands[2]);
12122
12123 rtx scratch1 = gen_reg_rtx (SImode);
12124 rtx scratch2 = gen_reg_rtx (SImode);
12125 emit_move_insn (scratch1, op2_high);
12126 emit_move_insn (scratch2, op1_high);
12127
12128 emit_insn(gen_rtx_SET(scratch1,
12129 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
12130 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
12131 emit_move_insn (op0_low, op1_low);
12132 emit_move_insn (op0_high, scratch2);
12133
12134 DONE;
12135 }"
12136 )
12137
12138 ;; movmisalign patterns for HImode and SImode.
12139 (define_expand "movmisalign<mode>"
12140 [(match_operand:HSI 0 "general_operand")
12141 (match_operand:HSI 1 "general_operand")]
12142 "unaligned_access"
12143 {
12144 /* This pattern is not permitted to fail during expansion: if both arguments
12145 are non-registers (e.g. memory := constant), force operand 1 into a
12146 register. */
12147 rtx (* gen_unaligned_load)(rtx, rtx);
12148 rtx tmp_dest = operands[0];
12149 if (!s_register_operand (operands[0], <MODE>mode)
12150 && !s_register_operand (operands[1], <MODE>mode))
12151 operands[1] = force_reg (<MODE>mode, operands[1]);
12152
12153 if (<MODE>mode == HImode)
12154 {
12155 gen_unaligned_load = gen_unaligned_loadhiu;
12156 tmp_dest = gen_reg_rtx (SImode);
12157 }
12158 else
12159 gen_unaligned_load = gen_unaligned_loadsi;
12160
12161 if (MEM_P (operands[1]))
12162 {
12163 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
12164 if (<MODE>mode == HImode)
12165 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
12166 }
12167 else
12168 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
12169
12170 DONE;
12171 })
12172
12173 (define_insn "<cdp>"
12174 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12175 (match_operand:SI 1 "immediate_operand" "n")
12176 (match_operand:SI 2 "immediate_operand" "n")
12177 (match_operand:SI 3 "immediate_operand" "n")
12178 (match_operand:SI 4 "immediate_operand" "n")
12179 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
12180 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
12181 {
12182 arm_const_bounds (operands[0], 0, 16);
12183 arm_const_bounds (operands[1], 0, 16);
12184 arm_const_bounds (operands[2], 0, (1 << 5));
12185 arm_const_bounds (operands[3], 0, (1 << 5));
12186 arm_const_bounds (operands[4], 0, (1 << 5));
12187 arm_const_bounds (operands[5], 0, 8);
12188 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
12189 }
12190 [(set_attr "length" "4")
12191 (set_attr "type" "coproc")])
12192
12193 (define_insn "*ldc"
12194 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12195 (match_operand:SI 1 "immediate_operand" "n")
12196 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
12197 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
12198 {
12199 arm_const_bounds (operands[0], 0, 16);
12200 arm_const_bounds (operands[1], 0, (1 << 5));
12201 return "<ldc>\\tp%c0, CR%c1, %2";
12202 }
12203 [(set_attr "length" "4")
12204 (set_attr "type" "coproc")])
12205
12206 (define_insn "*stc"
12207 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12208 (match_operand:SI 1 "immediate_operand" "n")
12209 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
12210 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
12211 {
12212 arm_const_bounds (operands[0], 0, 16);
12213 arm_const_bounds (operands[1], 0, (1 << 5));
12214 return "<stc>\\tp%c0, CR%c1, %2";
12215 }
12216 [(set_attr "length" "4")
12217 (set_attr "type" "coproc")])
12218
12219 (define_expand "<ldc>"
12220 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12221 (match_operand:SI 1 "immediate_operand")
12222 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
12223 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
12224
12225 (define_expand "<stc>"
12226 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
12227 (match_operand:SI 1 "immediate_operand")
12228 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
12229 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
12230
12231 (define_insn "<mcr>"
12232 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12233 (match_operand:SI 1 "immediate_operand" "n")
12234 (match_operand:SI 2 "s_register_operand" "r")
12235 (match_operand:SI 3 "immediate_operand" "n")
12236 (match_operand:SI 4 "immediate_operand" "n")
12237 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
12238 (use (match_dup 2))]
12239 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
12240 {
12241 arm_const_bounds (operands[0], 0, 16);
12242 arm_const_bounds (operands[1], 0, 8);
12243 arm_const_bounds (operands[3], 0, (1 << 5));
12244 arm_const_bounds (operands[4], 0, (1 << 5));
12245 arm_const_bounds (operands[5], 0, 8);
12246 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
12247 }
12248 [(set_attr "length" "4")
12249 (set_attr "type" "coproc")])
12250
12251 (define_insn "<mrc>"
12252 [(set (match_operand:SI 0 "s_register_operand" "=r")
12253 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
12254 (match_operand:SI 2 "immediate_operand" "n")
12255 (match_operand:SI 3 "immediate_operand" "n")
12256 (match_operand:SI 4 "immediate_operand" "n")
12257 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12258 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12259 {
12260 arm_const_bounds (operands[1], 0, 16);
12261 arm_const_bounds (operands[2], 0, 8);
12262 arm_const_bounds (operands[3], 0, (1 << 5));
12263 arm_const_bounds (operands[4], 0, (1 << 5));
12264 arm_const_bounds (operands[5], 0, 8);
12265 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12266 }
12267 [(set_attr "length" "4")
12268 (set_attr "type" "coproc")])
12269
12270 (define_insn "<mcrr>"
12271 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12272 (match_operand:SI 1 "immediate_operand" "n")
12273 (match_operand:DI 2 "s_register_operand" "r")
12274 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
12275 (use (match_dup 2))]
12276 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
12277 {
12278 arm_const_bounds (operands[0], 0, 16);
12279 arm_const_bounds (operands[1], 0, 8);
12280 arm_const_bounds (operands[3], 0, (1 << 5));
12281 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
12282 }
12283 [(set_attr "length" "4")
12284 (set_attr "type" "coproc")])
12285
12286 (define_insn "<mrrc>"
12287 [(set (match_operand:DI 0 "s_register_operand" "=r")
12288 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
12289 (match_operand:SI 2 "immediate_operand" "n")
12290 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
12291 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
12292 {
12293 arm_const_bounds (operands[1], 0, 16);
12294 arm_const_bounds (operands[2], 0, 8);
12295 arm_const_bounds (operands[3], 0, (1 << 5));
12296 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
12297 }
12298 [(set_attr "length" "4")
12299 (set_attr "type" "coproc")])
12300
12301 (define_expand "speculation_barrier"
12302 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
12303 "TARGET_EITHER"
12304 "
12305 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
12306 have a usable barrier (and probably don't need one in practice).
12307 But to be safe if such code is run on later architectures, call a
12308 helper function in libgcc that will do the thing for the active
12309 system. */
12310 if (!(arm_arch7 || arm_arch8))
12311 {
12312 arm_emit_speculation_barrier_function ();
12313 DONE;
12314 }
12315 "
12316 )
12317
12318 ;; Generate a hard speculation barrier when we have not enabled speculation
12319 ;; tracking.
12320 (define_insn "*speculation_barrier_insn"
12321 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
12322 "arm_arch7 || arm_arch8"
12323 "isb\;dsb\\tsy"
12324 [(set_attr "type" "block")
12325 (set_attr "length" "8")]
12326 )
12327
12328 ;; Vector bits common to IWMMXT and Neon
12329 (include "vec-common.md")
12330 ;; Load the Intel Wireless Multimedia Extension patterns
12331 (include "iwmmxt.md")
12332 ;; Load the VFP co-processor patterns
12333 (include "vfp.md")
12334 ;; Thumb-1 patterns
12335 (include "thumb1.md")
12336 ;; Thumb-2 patterns
12337 (include "thumb2.md")
12338 ;; Neon patterns
12339 (include "neon.md")
12340 ;; Crypto patterns
12341 (include "crypto.md")
12342 ;; Synchronization Primitives
12343 (include "sync.md")
12344 ;; Fixed-point patterns
12345 (include "arm-fixed.md")