]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/arm.md
[ARM] Add missing TARGET_32BIT conditional to movsi
[thirdparty/gcc.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright (C) 1991-2017 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 (IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (LAST_ARM_REGNUM 15) ;
38 (CC_REGNUM 100) ; Condition code pseudo register
39 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
40 ]
41 )
42 ;; 3rd operand to select_dominance_cc_mode
43 (define_constants
44 [(DOM_CC_X_AND_Y 0)
45 (DOM_CC_NX_OR_Y 1)
46 (DOM_CC_X_OR_Y 2)
47 ]
48 )
49 ;; conditional compare combination
50 (define_constants
51 [(CMP_CMP 0)
52 (CMN_CMP 1)
53 (CMP_CMN 2)
54 (CMN_CMN 3)
55 (NUM_OF_COND_CMP 4)
56 ]
57 )
58
59 \f
60 ;;---------------------------------------------------------------------------
61 ;; Attributes
62
63 ;; Processor type. This is created automatically from arm-cores.def.
64 (include "arm-tune.md")
65
66 ;; Instruction classification types
67 (include "types.md")
68
69 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
70 ; generating ARM code. This is used to control the length of some insn
71 ; patterns that share the same RTL in both ARM and Thumb code.
72 (define_attr "is_thumb" "yes,no"
73 (const (if_then_else (symbol_ref "TARGET_THUMB")
74 (const_string "yes") (const_string "no"))))
75
76 ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
77 (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
78
79 ; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
80 (define_attr "is_thumb1" "yes,no"
81 (const (if_then_else (symbol_ref "TARGET_THUMB1")
82 (const_string "yes") (const_string "no"))))
83
84 ; We use this attribute to disable alternatives that can produce 32-bit
85 ; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
86 ; that contain 32-bit instructions.
87 (define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
88
89 ; This attribute is used to disable a predicated alternative when we have
90 ; arm_restrict_it.
91 (define_attr "predicable_short_it" "no,yes" (const_string "yes"))
92
93 ;; Operand number of an input operand that is shifted. Zero if the
94 ;; given instruction does not shift one of its input operands.
95 (define_attr "shift" "" (const_int 0))
96
97 ;; [For compatibility with AArch64 in pipeline models]
98 ;; Attribute that specifies whether or not the instruction touches fp
99 ;; registers.
100 (define_attr "fp" "no,yes" (const_string "no"))
101
102 ; Floating Point Unit. If we only have floating point emulation, then there
103 ; is no point in scheduling the floating point insns. (Well, for best
104 ; performance we should try and group them together).
105 (define_attr "fpu" "none,vfp"
106 (const (symbol_ref "arm_fpu_attr")))
107
108 ; Predicated means that the insn form is conditionally executed based on a
109 ; predicate. We default to 'no' because no Thumb patterns match this rule
110 ; and not all ARM insns do.
111 (define_attr "predicated" "yes,no" (const_string "no"))
112
113 ; LENGTH of an instruction (in bytes)
114 (define_attr "length" ""
115 (const_int 4))
116
117 ; The architecture which supports the instruction (or alternative).
118 ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
119 ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
120 ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
121 ; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
122 ; Baseline. This attribute is used to compute attribute "enabled",
123 ; use type "any" to enable an alternative in all cases.
124 (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"
125 (const_string "any"))
126
127 (define_attr "arch_enabled" "no,yes"
128 (cond [(eq_attr "arch" "any")
129 (const_string "yes")
130
131 (and (eq_attr "arch" "a")
132 (match_test "TARGET_ARM"))
133 (const_string "yes")
134
135 (and (eq_attr "arch" "t")
136 (match_test "TARGET_THUMB"))
137 (const_string "yes")
138
139 (and (eq_attr "arch" "t1")
140 (match_test "TARGET_THUMB1"))
141 (const_string "yes")
142
143 (and (eq_attr "arch" "t2")
144 (match_test "TARGET_THUMB2"))
145 (const_string "yes")
146
147 (and (eq_attr "arch" "32")
148 (match_test "TARGET_32BIT"))
149 (const_string "yes")
150
151 (and (eq_attr "arch" "v6")
152 (match_test "TARGET_32BIT && arm_arch6"))
153 (const_string "yes")
154
155 (and (eq_attr "arch" "nov6")
156 (match_test "TARGET_32BIT && !arm_arch6"))
157 (const_string "yes")
158
159 (and (eq_attr "arch" "v6t2")
160 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
161 (const_string "yes")
162
163 (and (eq_attr "arch" "v8mb")
164 (match_test "TARGET_THUMB1 && arm_arch8"))
165 (const_string "yes")
166
167 (and (eq_attr "arch" "avoid_neon_for_64bits")
168 (match_test "TARGET_NEON")
169 (not (match_test "TARGET_PREFER_NEON_64BITS")))
170 (const_string "yes")
171
172 (and (eq_attr "arch" "neon_for_64bits")
173 (match_test "TARGET_NEON")
174 (match_test "TARGET_PREFER_NEON_64BITS"))
175 (const_string "yes")
176
177 (and (eq_attr "arch" "iwmmxt2")
178 (match_test "TARGET_REALLY_IWMMXT2"))
179 (const_string "yes")
180
181 (and (eq_attr "arch" "armv6_or_vfpv3")
182 (match_test "arm_arch6 || TARGET_VFP3"))
183 (const_string "yes")
184
185 (and (eq_attr "arch" "neon")
186 (match_test "TARGET_NEON"))
187 (const_string "yes")
188 ]
189
190 (const_string "no")))
191
192 (define_attr "opt" "any,speed,size"
193 (const_string "any"))
194
195 (define_attr "opt_enabled" "no,yes"
196 (cond [(eq_attr "opt" "any")
197 (const_string "yes")
198
199 (and (eq_attr "opt" "speed")
200 (match_test "optimize_function_for_speed_p (cfun)"))
201 (const_string "yes")
202
203 (and (eq_attr "opt" "size")
204 (match_test "optimize_function_for_size_p (cfun)"))
205 (const_string "yes")]
206 (const_string "no")))
207
208 (define_attr "use_literal_pool" "no,yes"
209 (cond [(and (eq_attr "type" "f_loads,f_loadd")
210 (match_test "CONSTANT_P (operands[1])"))
211 (const_string "yes")]
212 (const_string "no")))
213
214 ; Enable all alternatives that are both arch_enabled and insn_enabled.
215 ; FIXME:: opt_enabled has been temporarily removed till the time we have
216 ; an attribute that allows the use of such alternatives.
217 ; This depends on caching of speed_p, size_p on a per
218 ; alternative basis. The problem is that the enabled attribute
219 ; cannot depend on any state that is not cached or is not constant
220 ; for a compilation unit. We probably need a generic "hot/cold"
221 ; alternative which if implemented can help with this. We disable this
222 ; until such a time as this is implemented and / or the improvements or
223 ; regressions with removing this attribute are double checked.
224 ; See ashldi3_neon and <shift>di3_neon in neon.md.
225
226 (define_attr "enabled" "no,yes"
227 (cond [(and (eq_attr "predicable_short_it" "no")
228 (and (eq_attr "predicated" "yes")
229 (match_test "arm_restrict_it")))
230 (const_string "no")
231
232 (and (eq_attr "enabled_for_depr_it" "no")
233 (match_test "arm_restrict_it"))
234 (const_string "no")
235
236 (eq_attr "arch_enabled" "no")
237 (const_string "no")]
238 (const_string "yes")))
239
240 ; POOL_RANGE is how far away from a constant pool entry that this insn
241 ; can be placed. If the distance is zero, then this insn will never
242 ; reference the pool.
243 ; Note that for Thumb constant pools the PC value is rounded down to the
244 ; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
245 ; Thumb insns) should be set to <max_range> - 2.
246 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
247 ; before its address. It is set to <max_range> - (8 + <data_size>).
248 (define_attr "arm_pool_range" "" (const_int 0))
249 (define_attr "thumb2_pool_range" "" (const_int 0))
250 (define_attr "arm_neg_pool_range" "" (const_int 0))
251 (define_attr "thumb2_neg_pool_range" "" (const_int 0))
252
253 (define_attr "pool_range" ""
254 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
255 (attr "arm_pool_range")))
256 (define_attr "neg_pool_range" ""
257 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
258 (attr "arm_neg_pool_range")))
259
260 ; An assembler sequence may clobber the condition codes without us knowing.
261 ; If such an insn references the pool, then we have no way of knowing how,
262 ; so use the most conservative value for pool_range.
263 (define_asm_attributes
264 [(set_attr "conds" "clob")
265 (set_attr "length" "4")
266 (set_attr "pool_range" "250")])
267
268 ; Load scheduling, set from the arm_ld_sched variable
269 ; initialized by arm_option_override()
270 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
271
272 ; condition codes: this one is used by final_prescan_insn to speed up
273 ; conditionalizing instructions. It saves having to scan the rtl to see if
274 ; it uses or alters the condition codes.
275 ;
276 ; USE means that the condition codes are used by the insn in the process of
277 ; outputting code, this means (at present) that we can't use the insn in
278 ; inlined branches
279 ;
280 ; SET means that the purpose of the insn is to set the condition codes in a
281 ; well defined manner.
282 ;
283 ; CLOB means that the condition codes are altered in an undefined manner, if
284 ; they are altered at all
285 ;
286 ; UNCONDITIONAL means the instruction can not be conditionally executed and
287 ; that the instruction does not use or alter the condition codes.
288 ;
289 ; NOCOND means that the instruction does not use or alter the condition
290 ; codes but can be converted into a conditionally exectuted instruction.
291
292 (define_attr "conds" "use,set,clob,unconditional,nocond"
293 (if_then_else
294 (ior (eq_attr "is_thumb1" "yes")
295 (eq_attr "type" "call"))
296 (const_string "clob")
297 (if_then_else (eq_attr "is_neon_type" "no")
298 (const_string "nocond")
299 (const_string "unconditional"))))
300
301 ; Predicable means that the insn can be conditionally executed based on
302 ; an automatically added predicate (additional patterns are generated by
303 ; gen...). We default to 'no' because no Thumb patterns match this rule
304 ; and not all ARM patterns do.
305 (define_attr "predicable" "no,yes" (const_string "no"))
306
307 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
308 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
309 ; suffer blockages enough to warrant modelling this (and it can adversely
310 ; affect the schedule).
311 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
312
313 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
314 ; to stall the processor. Used with model_wbuf above.
315 (define_attr "write_conflict" "no,yes"
316 (if_then_else (eq_attr "type"
317 "block,call,load1")
318 (const_string "yes")
319 (const_string "no")))
320
321 ; Classify the insns into those that take one cycle and those that take more
322 ; than one on the main cpu execution unit.
323 (define_attr "core_cycles" "single,multi"
324 (if_then_else (eq_attr "type"
325 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
326 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
327 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
328 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
329 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
330 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
331 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
332 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
333 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
334 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
335 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
336 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
337 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
338 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
339 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
340 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
341 (const_string "single")
342 (const_string "multi")))
343
344 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
345 ;; distant label. Only applicable to Thumb code.
346 (define_attr "far_jump" "yes,no" (const_string "no"))
347
348
349 ;; The number of machine instructions this pattern expands to.
350 ;; Used for Thumb-2 conditional execution.
351 (define_attr "ce_count" "" (const_int 1))
352
353 ;;---------------------------------------------------------------------------
354 ;; Unspecs
355
356 (include "unspecs.md")
357
358 ;;---------------------------------------------------------------------------
359 ;; Mode iterators
360
361 (include "iterators.md")
362
363 ;;---------------------------------------------------------------------------
364 ;; Predicates
365
366 (include "predicates.md")
367 (include "constraints.md")
368
369 ;;---------------------------------------------------------------------------
370 ;; Pipeline descriptions
371
372 (define_attr "tune_cortexr4" "yes,no"
373 (const (if_then_else
374 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
375 (const_string "yes")
376 (const_string "no"))))
377
378 ;; True if the generic scheduling description should be used.
379
380 (define_attr "generic_sched" "yes,no"
381 (const (if_then_else
382 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
383 arm926ejs,arm1020e,arm1026ejs,arm1136js,\
384 arm1136jfs,cortexa5,cortexa7,cortexa8,\
385 cortexa9,cortexa12,cortexa15,cortexa17,\
386 cortexa53,cortexa57,cortexm4,cortexm7,\
387 exynosm1,marvell_pj4,xgene1")
388 (eq_attr "tune_cortexr4" "yes"))
389 (const_string "no")
390 (const_string "yes"))))
391
392 (define_attr "generic_vfp" "yes,no"
393 (const (if_then_else
394 (and (eq_attr "fpu" "vfp")
395 (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
396 cortexa8,cortexa9,cortexa53,cortexm4,\
397 cortexm7,marvell_pj4,xgene1")
398 (eq_attr "tune_cortexr4" "no"))
399 (const_string "yes")
400 (const_string "no"))))
401
402 (include "marvell-f-iwmmxt.md")
403 (include "arm-generic.md")
404 (include "arm926ejs.md")
405 (include "arm1020e.md")
406 (include "arm1026ejs.md")
407 (include "arm1136jfs.md")
408 (include "fa526.md")
409 (include "fa606te.md")
410 (include "fa626te.md")
411 (include "fmp626.md")
412 (include "fa726te.md")
413 (include "cortex-a5.md")
414 (include "cortex-a7.md")
415 (include "cortex-a8.md")
416 (include "cortex-a9.md")
417 (include "cortex-a15.md")
418 (include "cortex-a17.md")
419 (include "cortex-a53.md")
420 (include "cortex-a57.md")
421 (include "cortex-r4.md")
422 (include "cortex-r4f.md")
423 (include "cortex-m7.md")
424 (include "cortex-m4.md")
425 (include "cortex-m4-fpu.md")
426 (include "exynos-m1.md")
427 (include "vfp11.md")
428 (include "marvell-pj4.md")
429 (include "xgene1.md")
430
431 \f
432 ;;---------------------------------------------------------------------------
433 ;; Insn patterns
434 ;;
435 ;; Addition insns.
436
437 ;; Note: For DImode insns, there is normally no reason why operands should
438 ;; not be in the same register, what we don't want is for something being
439 ;; written to partially overlap something that is an input.
440
441 (define_expand "adddi3"
442 [(parallel
443 [(set (match_operand:DI 0 "s_register_operand" "")
444 (plus:DI (match_operand:DI 1 "s_register_operand" "")
445 (match_operand:DI 2 "arm_adddi_operand" "")))
446 (clobber (reg:CC CC_REGNUM))])]
447 "TARGET_EITHER"
448 "
449 if (TARGET_THUMB1)
450 {
451 if (!REG_P (operands[1]))
452 operands[1] = force_reg (DImode, operands[1]);
453 if (!REG_P (operands[2]))
454 operands[2] = force_reg (DImode, operands[2]);
455 }
456 "
457 )
458
459 (define_insn_and_split "*arm_adddi3"
460 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
461 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
462 (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
463 (clobber (reg:CC CC_REGNUM))]
464 "TARGET_32BIT && !TARGET_NEON"
465 "#"
466 "TARGET_32BIT && reload_completed
467 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
468 [(parallel [(set (reg:CC_C CC_REGNUM)
469 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
470 (match_dup 1)))
471 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
472 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
473 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
474 "
475 {
476 operands[3] = gen_highpart (SImode, operands[0]);
477 operands[0] = gen_lowpart (SImode, operands[0]);
478 operands[4] = gen_highpart (SImode, operands[1]);
479 operands[1] = gen_lowpart (SImode, operands[1]);
480 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
481 operands[2] = gen_lowpart (SImode, operands[2]);
482 }"
483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")
485 (set_attr "type" "multiple")]
486 )
487
488 (define_insn_and_split "*adddi_sesidi_di"
489 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
490 (plus:DI (sign_extend:DI
491 (match_operand:SI 2 "s_register_operand" "r,r"))
492 (match_operand:DI 1 "s_register_operand" "0,r")))
493 (clobber (reg:CC CC_REGNUM))]
494 "TARGET_32BIT"
495 "#"
496 "TARGET_32BIT && reload_completed"
497 [(parallel [(set (reg:CC_C CC_REGNUM)
498 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
499 (match_dup 1)))
500 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
501 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
502 (const_int 31))
503 (match_dup 4))
504 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
505 "
506 {
507 operands[3] = gen_highpart (SImode, operands[0]);
508 operands[0] = gen_lowpart (SImode, operands[0]);
509 operands[4] = gen_highpart (SImode, operands[1]);
510 operands[1] = gen_lowpart (SImode, operands[1]);
511 operands[2] = gen_lowpart (SImode, operands[2]);
512 }"
513 [(set_attr "conds" "clob")
514 (set_attr "length" "8")
515 (set_attr "type" "multiple")]
516 )
517
518 (define_insn_and_split "*adddi_zesidi_di"
519 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
520 (plus:DI (zero_extend:DI
521 (match_operand:SI 2 "s_register_operand" "r,r"))
522 (match_operand:DI 1 "s_register_operand" "0,r")))
523 (clobber (reg:CC CC_REGNUM))]
524 "TARGET_32BIT"
525 "#"
526 "TARGET_32BIT && reload_completed"
527 [(parallel [(set (reg:CC_C CC_REGNUM)
528 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
529 (match_dup 1)))
530 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
531 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
532 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
533 "
534 {
535 operands[3] = gen_highpart (SImode, operands[0]);
536 operands[0] = gen_lowpart (SImode, operands[0]);
537 operands[4] = gen_highpart (SImode, operands[1]);
538 operands[1] = gen_lowpart (SImode, operands[1]);
539 operands[2] = gen_lowpart (SImode, operands[2]);
540 }"
541 [(set_attr "conds" "clob")
542 (set_attr "length" "8")
543 (set_attr "type" "multiple")]
544 )
545
546 (define_expand "addv<mode>4"
547 [(match_operand:SIDI 0 "register_operand")
548 (match_operand:SIDI 1 "register_operand")
549 (match_operand:SIDI 2 "register_operand")
550 (match_operand 3 "")]
551 "TARGET_32BIT"
552 {
553 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
554 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
555
556 DONE;
557 })
558
559 (define_expand "uaddv<mode>4"
560 [(match_operand:SIDI 0 "register_operand")
561 (match_operand:SIDI 1 "register_operand")
562 (match_operand:SIDI 2 "register_operand")
563 (match_operand 3 "")]
564 "TARGET_32BIT"
565 {
566 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
567 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
568
569 DONE;
570 })
571
572 (define_expand "addsi3"
573 [(set (match_operand:SI 0 "s_register_operand" "")
574 (plus:SI (match_operand:SI 1 "s_register_operand" "")
575 (match_operand:SI 2 "reg_or_int_operand" "")))]
576 "TARGET_EITHER"
577 "
578 if (TARGET_32BIT && CONST_INT_P (operands[2]))
579 {
580 arm_split_constant (PLUS, SImode, NULL_RTX,
581 INTVAL (operands[2]), operands[0], operands[1],
582 optimize && can_create_pseudo_p ());
583 DONE;
584 }
585 "
586 )
587
588 ; If there is a scratch available, this will be faster than synthesizing the
589 ; addition.
590 (define_peephole2
591 [(match_scratch:SI 3 "r")
592 (set (match_operand:SI 0 "arm_general_register_operand" "")
593 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
594 (match_operand:SI 2 "const_int_operand" "")))]
595 "TARGET_32BIT &&
596 !(const_ok_for_arm (INTVAL (operands[2]))
597 || const_ok_for_arm (-INTVAL (operands[2])))
598 && const_ok_for_arm (~INTVAL (operands[2]))"
599 [(set (match_dup 3) (match_dup 2))
600 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
601 ""
602 )
603
604 ;; The r/r/k alternative is required when reloading the address
605 ;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
606 ;; put the duplicated register first, and not try the commutative version.
607 (define_insn_and_split "*arm_addsi3"
608 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
609 (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")
610 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
611 "TARGET_32BIT"
612 "@
613 add%?\\t%0, %0, %2
614 add%?\\t%0, %1, %2
615 add%?\\t%0, %1, %2
616 add%?\\t%0, %1, %2
617 add%?\\t%0, %1, %2
618 add%?\\t%0, %1, %2
619 add%?\\t%0, %2, %1
620 add%?\\t%0, %1, %2
621 addw%?\\t%0, %1, %2
622 addw%?\\t%0, %1, %2
623 sub%?\\t%0, %1, #%n2
624 sub%?\\t%0, %1, #%n2
625 sub%?\\t%0, %1, #%n2
626 subw%?\\t%0, %1, #%n2
627 subw%?\\t%0, %1, #%n2
628 #"
629 "TARGET_32BIT
630 && CONST_INT_P (operands[2])
631 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
632 && (reload_completed || !arm_eliminable_register (operands[1]))"
633 [(clobber (const_int 0))]
634 "
635 arm_split_constant (PLUS, SImode, curr_insn,
636 INTVAL (operands[2]), operands[0],
637 operands[1], 0);
638 DONE;
639 "
640 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
641 (set_attr "predicable" "yes")
642 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
643 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
644 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
645 (const_string "alu_imm")
646 (const_string "alu_sreg")))
647 ]
648 )
649
650 (define_insn_and_split "adddi3_compareV"
651 [(set (reg:CC_V CC_REGNUM)
652 (ne:CC_V
653 (plus:TI
654 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
655 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
656 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
657 (set (match_operand:DI 0 "register_operand" "=&r")
658 (plus:DI (match_dup 1) (match_dup 2)))]
659 "TARGET_32BIT"
660 "#"
661 "&& reload_completed"
662 [(parallel [(set (reg:CC_C CC_REGNUM)
663 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
664 (match_dup 1)))
665 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
666 (parallel [(set (reg:CC_V CC_REGNUM)
667 (ne:CC_V
668 (plus:DI (plus:DI
669 (sign_extend:DI (match_dup 4))
670 (sign_extend:DI (match_dup 5)))
671 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
672 (plus:DI (sign_extend:DI
673 (plus:SI (match_dup 4) (match_dup 5)))
674 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
675 (set (match_dup 3) (plus:SI (plus:SI
676 (match_dup 4) (match_dup 5))
677 (ltu:SI (reg:CC_C CC_REGNUM)
678 (const_int 0))))])]
679 "
680 {
681 operands[3] = gen_highpart (SImode, operands[0]);
682 operands[0] = gen_lowpart (SImode, operands[0]);
683 operands[4] = gen_highpart (SImode, operands[1]);
684 operands[1] = gen_lowpart (SImode, operands[1]);
685 operands[5] = gen_highpart (SImode, operands[2]);
686 operands[2] = gen_lowpart (SImode, operands[2]);
687 }"
688 [(set_attr "conds" "set")
689 (set_attr "length" "8")
690 (set_attr "type" "multiple")]
691 )
692
693 (define_insn "addsi3_compareV"
694 [(set (reg:CC_V CC_REGNUM)
695 (ne:CC_V
696 (plus:DI
697 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
698 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
699 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
700 (set (match_operand:SI 0 "register_operand" "=r")
701 (plus:SI (match_dup 1) (match_dup 2)))]
702 "TARGET_32BIT"
703 "adds%?\\t%0, %1, %2"
704 [(set_attr "conds" "set")
705 (set_attr "type" "alus_sreg")]
706 )
707
708 (define_insn "*addsi3_compareV_upper"
709 [(set (reg:CC_V CC_REGNUM)
710 (ne:CC_V
711 (plus:DI
712 (plus:DI
713 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
714 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
715 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
716 (plus:DI (sign_extend:DI
717 (plus:SI (match_dup 1) (match_dup 2)))
718 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
719 (set (match_operand:SI 0 "register_operand" "=r")
720 (plus:SI
721 (plus:SI (match_dup 1) (match_dup 2))
722 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
723 "TARGET_32BIT"
724 "adcs%?\\t%0, %1, %2"
725 [(set_attr "conds" "set")
726 (set_attr "type" "adcs_reg")]
727 )
728
729 (define_insn_and_split "adddi3_compareC"
730 [(set (reg:CC_C CC_REGNUM)
731 (ne:CC_C
732 (plus:TI
733 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
734 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
735 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
736 (set (match_operand:DI 0 "register_operand" "=&r")
737 (plus:DI (match_dup 1) (match_dup 2)))]
738 "TARGET_32BIT"
739 "#"
740 "&& reload_completed"
741 [(parallel [(set (reg:CC_C CC_REGNUM)
742 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
743 (match_dup 1)))
744 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
745 (parallel [(set (reg:CC_C CC_REGNUM)
746 (ne:CC_C
747 (plus:DI (plus:DI
748 (zero_extend:DI (match_dup 4))
749 (zero_extend:DI (match_dup 5)))
750 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
751 (plus:DI (zero_extend:DI
752 (plus:SI (match_dup 4) (match_dup 5)))
753 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
754 (set (match_dup 3) (plus:SI
755 (plus:SI (match_dup 4) (match_dup 5))
756 (ltu:SI (reg:CC_C CC_REGNUM)
757 (const_int 0))))])]
758 "
759 {
760 operands[3] = gen_highpart (SImode, operands[0]);
761 operands[0] = gen_lowpart (SImode, operands[0]);
762 operands[4] = gen_highpart (SImode, operands[1]);
763 operands[5] = gen_highpart (SImode, operands[2]);
764 operands[1] = gen_lowpart (SImode, operands[1]);
765 operands[2] = gen_lowpart (SImode, operands[2]);
766 }"
767 [(set_attr "conds" "set")
768 (set_attr "length" "8")
769 (set_attr "type" "multiple")]
770 )
771
772 (define_insn "*addsi3_compareC_upper"
773 [(set (reg:CC_C CC_REGNUM)
774 (ne:CC_C
775 (plus:DI
776 (plus:DI
777 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
778 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
779 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
780 (plus:DI (zero_extend:DI
781 (plus:SI (match_dup 1) (match_dup 2)))
782 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
783 (set (match_operand:SI 0 "register_operand" "=r")
784 (plus:SI
785 (plus:SI (match_dup 1) (match_dup 2))
786 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
787 "TARGET_32BIT"
788 "adcs%?\\t%0, %1, %2"
789 [(set_attr "conds" "set")
790 (set_attr "type" "adcs_reg")]
791 )
792
793 (define_insn "addsi3_compareC"
794 [(set (reg:CC_C CC_REGNUM)
795 (ne:CC_C
796 (plus:DI
797 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
798 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
799 (zero_extend:DI
800 (plus:SI (match_dup 1) (match_dup 2)))))
801 (set (match_operand:SI 0 "register_operand" "=r")
802 (plus:SI (match_dup 1) (match_dup 2)))]
803 "TARGET_32BIT"
804 "adds%?\\t%0, %1, %2"
805 [(set_attr "conds" "set")
806 (set_attr "type" "alus_sreg")]
807 )
808
809 (define_insn "addsi3_compare0"
810 [(set (reg:CC_NOOV CC_REGNUM)
811 (compare:CC_NOOV
812 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
813 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
814 (const_int 0)))
815 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
816 (plus:SI (match_dup 1) (match_dup 2)))]
817 "TARGET_ARM"
818 "@
819 adds%?\\t%0, %1, %2
820 subs%?\\t%0, %1, #%n2
821 adds%?\\t%0, %1, %2"
822 [(set_attr "conds" "set")
823 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
824 )
825
826 (define_insn "*addsi3_compare0_scratch"
827 [(set (reg:CC_NOOV CC_REGNUM)
828 (compare:CC_NOOV
829 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
830 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
831 (const_int 0)))]
832 "TARGET_ARM"
833 "@
834 cmn%?\\t%0, %1
835 cmp%?\\t%0, #%n1
836 cmn%?\\t%0, %1"
837 [(set_attr "conds" "set")
838 (set_attr "predicable" "yes")
839 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
840 )
841
842 (define_insn "*compare_negsi_si"
843 [(set (reg:CC_Z CC_REGNUM)
844 (compare:CC_Z
845 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
846 (match_operand:SI 1 "s_register_operand" "l,r")))]
847 "TARGET_32BIT"
848 "cmn%?\\t%1, %0"
849 [(set_attr "conds" "set")
850 (set_attr "predicable" "yes")
851 (set_attr "arch" "t2,*")
852 (set_attr "length" "2,4")
853 (set_attr "predicable_short_it" "yes,no")
854 (set_attr "type" "alus_sreg")]
855 )
856
857 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
858 ;; addend is a constant.
859 (define_insn "cmpsi2_addneg"
860 [(set (reg:CC CC_REGNUM)
861 (compare:CC
862 (match_operand:SI 1 "s_register_operand" "r,r")
863 (match_operand:SI 2 "arm_addimm_operand" "L,I")))
864 (set (match_operand:SI 0 "s_register_operand" "=r,r")
865 (plus:SI (match_dup 1)
866 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
867 "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
868 "@
869 adds%?\\t%0, %1, %3
870 subs%?\\t%0, %1, #%n3"
871 [(set_attr "conds" "set")
872 (set_attr "type" "alus_sreg")]
873 )
874
875 ;; Convert the sequence
876 ;; sub rd, rn, #1
877 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
878 ;; bne dest
879 ;; into
880 ;; subs rd, rn, #1
881 ;; bcs dest ((unsigned)rn >= 1)
882 ;; similarly for the beq variant using bcc.
883 ;; This is a common looping idiom (while (n--))
884 (define_peephole2
885 [(set (match_operand:SI 0 "arm_general_register_operand" "")
886 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
887 (const_int -1)))
888 (set (match_operand 2 "cc_register" "")
889 (compare (match_dup 0) (const_int -1)))
890 (set (pc)
891 (if_then_else (match_operator 3 "equality_operator"
892 [(match_dup 2) (const_int 0)])
893 (match_operand 4 "" "")
894 (match_operand 5 "" "")))]
895 "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
896 [(parallel[
897 (set (match_dup 2)
898 (compare:CC
899 (match_dup 1) (const_int 1)))
900 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
901 (set (pc)
902 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
903 (match_dup 4)
904 (match_dup 5)))]
905 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
906 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
907 ? GEU : LTU),
908 VOIDmode,
909 operands[2], const0_rtx);"
910 )
911
912 ;; The next four insns work because they compare the result with one of
913 ;; the operands, and we know that the use of the condition code is
914 ;; either GEU or LTU, so we can use the carry flag from the addition
915 ;; instead of doing the compare a second time.
916 (define_insn "*addsi3_compare_op1"
917 [(set (reg:CC_C CC_REGNUM)
918 (compare:CC_C
919 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
920 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
921 (match_dup 1)))
922 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
923 (plus:SI (match_dup 1) (match_dup 2)))]
924 "TARGET_32BIT"
925 "@
926 adds%?\\t%0, %1, %2
927 subs%?\\t%0, %1, #%n2
928 adds%?\\t%0, %1, %2"
929 [(set_attr "conds" "set")
930 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
931 )
932
933 (define_insn "*addsi3_compare_op2"
934 [(set (reg:CC_C CC_REGNUM)
935 (compare:CC_C
936 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
937 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
938 (match_dup 2)))
939 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
940 (plus:SI (match_dup 1) (match_dup 2)))]
941 "TARGET_32BIT"
942 "@
943 adds%?\\t%0, %1, %2
944 subs%?\\t%0, %1, #%n2
945 adds%?\\t%0, %1, %2"
946 [(set_attr "conds" "set")
947 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
948 )
949
950 (define_insn "*compare_addsi2_op0"
951 [(set (reg:CC_C CC_REGNUM)
952 (compare:CC_C
953 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
954 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
955 (match_dup 0)))]
956 "TARGET_32BIT"
957 "@
958 cmp%?\\t%0, #%n1
959 cmn%?\\t%0, %1
960 cmn%?\\t%0, %1
961 cmp%?\\t%0, #%n1
962 cmn%?\\t%0, %1"
963 [(set_attr "conds" "set")
964 (set_attr "predicable" "yes")
965 (set_attr "arch" "t2,t2,*,*,*")
966 (set_attr "predicable_short_it" "yes,yes,no,no,no")
967 (set_attr "length" "2,2,4,4,4")
968 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
969 )
970
971 (define_insn "*compare_addsi2_op1"
972 [(set (reg:CC_C CC_REGNUM)
973 (compare:CC_C
974 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
975 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
976 (match_dup 1)))]
977 "TARGET_32BIT"
978 "@
979 cmp%?\\t%0, #%n1
980 cmn%?\\t%0, %1
981 cmn%?\\t%0, %1
982 cmp%?\\t%0, #%n1
983 cmn%?\\t%0, %1"
984 [(set_attr "conds" "set")
985 (set_attr "predicable" "yes")
986 (set_attr "arch" "t2,t2,*,*,*")
987 (set_attr "predicable_short_it" "yes,yes,no,no,no")
988 (set_attr "length" "2,2,4,4,4")
989 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
990 )
991
992 (define_insn "*addsi3_carryin_<optab>"
993 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
994 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
995 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
996 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
997 "TARGET_32BIT"
998 "@
999 adc%?\\t%0, %1, %2
1000 adc%?\\t%0, %1, %2
1001 sbc%?\\t%0, %1, #%B2"
1002 [(set_attr "conds" "use")
1003 (set_attr "predicable" "yes")
1004 (set_attr "arch" "t2,*,*")
1005 (set_attr "length" "4")
1006 (set_attr "predicable_short_it" "yes,no,no")
1007 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1008 )
1009
1010 (define_insn "*addsi3_carryin_alt2_<optab>"
1011 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1012 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1013 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1014 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
1015 "TARGET_32BIT"
1016 "@
1017 adc%?\\t%0, %1, %2
1018 adc%?\\t%0, %1, %2
1019 sbc%?\\t%0, %1, #%B2"
1020 [(set_attr "conds" "use")
1021 (set_attr "predicable" "yes")
1022 (set_attr "arch" "t2,*,*")
1023 (set_attr "length" "4")
1024 (set_attr "predicable_short_it" "yes,no,no")
1025 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1026 )
1027
1028 (define_insn "*addsi3_carryin_shift_<optab>"
1029 [(set (match_operand:SI 0 "s_register_operand" "=r")
1030 (plus:SI (plus:SI
1031 (match_operator:SI 2 "shift_operator"
1032 [(match_operand:SI 3 "s_register_operand" "r")
1033 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1034 (match_operand:SI 1 "s_register_operand" "r"))
1035 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1036 "TARGET_32BIT"
1037 "adc%?\\t%0, %1, %3%S2"
1038 [(set_attr "conds" "use")
1039 (set_attr "predicable" "yes")
1040 (set_attr "predicable_short_it" "no")
1041 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1042 (const_string "alu_shift_imm")
1043 (const_string "alu_shift_reg")))]
1044 )
1045
1046 (define_insn "*addsi3_carryin_clobercc_<optab>"
1047 [(set (match_operand:SI 0 "s_register_operand" "=r")
1048 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1049 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1050 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1051 (clobber (reg:CC CC_REGNUM))]
1052 "TARGET_32BIT"
1053 "adcs%?\\t%0, %1, %2"
1054 [(set_attr "conds" "set")
1055 (set_attr "type" "adcs_reg")]
1056 )
1057
1058 (define_expand "subv<mode>4"
1059 [(match_operand:SIDI 0 "register_operand")
1060 (match_operand:SIDI 1 "register_operand")
1061 (match_operand:SIDI 2 "register_operand")
1062 (match_operand 3 "")]
1063 "TARGET_32BIT"
1064 {
1065 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1066 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
1067
1068 DONE;
1069 })
1070
1071 (define_expand "usubv<mode>4"
1072 [(match_operand:SIDI 0 "register_operand")
1073 (match_operand:SIDI 1 "register_operand")
1074 (match_operand:SIDI 2 "register_operand")
1075 (match_operand 3 "")]
1076 "TARGET_32BIT"
1077 {
1078 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1079 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1080
1081 DONE;
1082 })
1083
1084 (define_insn_and_split "subdi3_compare1"
1085 [(set (reg:CC CC_REGNUM)
1086 (compare:CC
1087 (match_operand:DI 1 "register_operand" "r")
1088 (match_operand:DI 2 "register_operand" "r")))
1089 (set (match_operand:DI 0 "register_operand" "=&r")
1090 (minus:DI (match_dup 1) (match_dup 2)))]
1091 "TARGET_32BIT"
1092 "#"
1093 "&& reload_completed"
1094 [(parallel [(set (reg:CC CC_REGNUM)
1095 (compare:CC (match_dup 1) (match_dup 2)))
1096 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1097 (parallel [(set (reg:CC CC_REGNUM)
1098 (compare:CC (match_dup 4) (match_dup 5)))
1099 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1100 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
1101 {
1102 operands[3] = gen_highpart (SImode, operands[0]);
1103 operands[0] = gen_lowpart (SImode, operands[0]);
1104 operands[4] = gen_highpart (SImode, operands[1]);
1105 operands[1] = gen_lowpart (SImode, operands[1]);
1106 operands[5] = gen_highpart (SImode, operands[2]);
1107 operands[2] = gen_lowpart (SImode, operands[2]);
1108 }
1109 [(set_attr "conds" "set")
1110 (set_attr "length" "8")
1111 (set_attr "type" "multiple")]
1112 )
1113
1114 (define_insn "subsi3_compare1"
1115 [(set (reg:CC CC_REGNUM)
1116 (compare:CC
1117 (match_operand:SI 1 "register_operand" "r")
1118 (match_operand:SI 2 "register_operand" "r")))
1119 (set (match_operand:SI 0 "register_operand" "=r")
1120 (minus:SI (match_dup 1) (match_dup 2)))]
1121 "TARGET_32BIT"
1122 "subs%?\\t%0, %1, %2"
1123 [(set_attr "conds" "set")
1124 (set_attr "type" "alus_sreg")]
1125 )
1126
1127 (define_insn "*subsi3_carryin"
1128 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1129 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1130 (match_operand:SI 2 "s_register_operand" "r,r,r"))
1131 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1132 "TARGET_32BIT"
1133 "@
1134 sbc%?\\t%0, %1, %2
1135 rsc%?\\t%0, %2, %1
1136 sbc%?\\t%0, %2, %2, lsl #1"
1137 [(set_attr "conds" "use")
1138 (set_attr "arch" "*,a,t2")
1139 (set_attr "predicable" "yes")
1140 (set_attr "predicable_short_it" "no")
1141 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
1142 )
1143
1144 (define_insn "*subsi3_carryin_const"
1145 [(set (match_operand:SI 0 "s_register_operand" "=r")
1146 (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1147 (match_operand:SI 2 "arm_not_immediate_operand" "K"))
1148 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1149 "TARGET_32BIT"
1150 "sbc\\t%0, %1, #%B2"
1151 [(set_attr "conds" "use")
1152 (set_attr "type" "adc_imm")]
1153 )
1154
1155 (define_insn "*subsi3_carryin_compare"
1156 [(set (reg:CC CC_REGNUM)
1157 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1158 (match_operand:SI 2 "s_register_operand" "r")))
1159 (set (match_operand:SI 0 "s_register_operand" "=r")
1160 (minus:SI (minus:SI (match_dup 1)
1161 (match_dup 2))
1162 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1163 "TARGET_32BIT"
1164 "sbcs\\t%0, %1, %2"
1165 [(set_attr "conds" "set")
1166 (set_attr "type" "adcs_reg")]
1167 )
1168
1169 (define_insn "*subsi3_carryin_compare_const"
1170 [(set (reg:CC CC_REGNUM)
1171 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1172 (match_operand:SI 2 "arm_not_operand" "K")))
1173 (set (match_operand:SI 0 "s_register_operand" "=r")
1174 (minus:SI (plus:SI (match_dup 1)
1175 (match_dup 2))
1176 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1177 "TARGET_32BIT"
1178 "sbcs\\t%0, %1, #%B2"
1179 [(set_attr "conds" "set")
1180 (set_attr "type" "adcs_imm")]
1181 )
1182
1183 (define_insn "*subsi3_carryin_shift"
1184 [(set (match_operand:SI 0 "s_register_operand" "=r")
1185 (minus:SI (minus:SI
1186 (match_operand:SI 1 "s_register_operand" "r")
1187 (match_operator:SI 2 "shift_operator"
1188 [(match_operand:SI 3 "s_register_operand" "r")
1189 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1190 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1191 "TARGET_32BIT"
1192 "sbc%?\\t%0, %1, %3%S2"
1193 [(set_attr "conds" "use")
1194 (set_attr "predicable" "yes")
1195 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1196 (const_string "alu_shift_imm")
1197 (const_string "alu_shift_reg")))]
1198 )
1199
1200 (define_insn "*rsbsi3_carryin_shift"
1201 [(set (match_operand:SI 0 "s_register_operand" "=r")
1202 (minus:SI (minus:SI
1203 (match_operator:SI 2 "shift_operator"
1204 [(match_operand:SI 3 "s_register_operand" "r")
1205 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1206 (match_operand:SI 1 "s_register_operand" "r"))
1207 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1208 "TARGET_ARM"
1209 "rsc%?\\t%0, %1, %3%S2"
1210 [(set_attr "conds" "use")
1211 (set_attr "predicable" "yes")
1212 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1213 (const_string "alu_shift_imm")
1214 (const_string "alu_shift_reg")))]
1215 )
1216
1217 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1218 (define_split
1219 [(set (match_operand:SI 0 "s_register_operand" "")
1220 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1221 (match_operand:SI 2 "s_register_operand" ""))
1222 (const_int -1)))
1223 (clobber (match_operand:SI 3 "s_register_operand" ""))]
1224 "TARGET_32BIT"
1225 [(set (match_dup 3) (match_dup 1))
1226 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1227 "
1228 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1229 ")
1230
1231 (define_expand "addsf3"
1232 [(set (match_operand:SF 0 "s_register_operand" "")
1233 (plus:SF (match_operand:SF 1 "s_register_operand" "")
1234 (match_operand:SF 2 "s_register_operand" "")))]
1235 "TARGET_32BIT && TARGET_HARD_FLOAT"
1236 "
1237 ")
1238
1239 (define_expand "adddf3"
1240 [(set (match_operand:DF 0 "s_register_operand" "")
1241 (plus:DF (match_operand:DF 1 "s_register_operand" "")
1242 (match_operand:DF 2 "s_register_operand" "")))]
1243 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1244 "
1245 ")
1246
1247 (define_expand "subdi3"
1248 [(parallel
1249 [(set (match_operand:DI 0 "s_register_operand" "")
1250 (minus:DI (match_operand:DI 1 "s_register_operand" "")
1251 (match_operand:DI 2 "s_register_operand" "")))
1252 (clobber (reg:CC CC_REGNUM))])]
1253 "TARGET_EITHER"
1254 "
1255 if (TARGET_THUMB1)
1256 {
1257 if (!REG_P (operands[1]))
1258 operands[1] = force_reg (DImode, operands[1]);
1259 if (!REG_P (operands[2]))
1260 operands[2] = force_reg (DImode, operands[2]);
1261 }
1262 "
1263 )
1264
1265 (define_insn_and_split "*arm_subdi3"
1266 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1267 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1268 (match_operand:DI 2 "s_register_operand" "r,0,0")))
1269 (clobber (reg:CC CC_REGNUM))]
1270 "TARGET_32BIT && !TARGET_NEON"
1271 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1272 "&& reload_completed"
1273 [(parallel [(set (reg:CC CC_REGNUM)
1274 (compare:CC (match_dup 1) (match_dup 2)))
1275 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1276 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1277 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1278 {
1279 operands[3] = gen_highpart (SImode, operands[0]);
1280 operands[0] = gen_lowpart (SImode, operands[0]);
1281 operands[4] = gen_highpart (SImode, operands[1]);
1282 operands[1] = gen_lowpart (SImode, operands[1]);
1283 operands[5] = gen_highpart (SImode, operands[2]);
1284 operands[2] = gen_lowpart (SImode, operands[2]);
1285 }
1286 [(set_attr "conds" "clob")
1287 (set_attr "length" "8")
1288 (set_attr "type" "multiple")]
1289 )
1290
1291 (define_insn_and_split "*subdi_di_zesidi"
1292 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1293 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1294 (zero_extend:DI
1295 (match_operand:SI 2 "s_register_operand" "r,r"))))
1296 (clobber (reg:CC CC_REGNUM))]
1297 "TARGET_32BIT"
1298 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1299 "&& reload_completed"
1300 [(parallel [(set (reg:CC CC_REGNUM)
1301 (compare:CC (match_dup 1) (match_dup 2)))
1302 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1303 (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1304 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1305 {
1306 operands[3] = gen_highpart (SImode, operands[0]);
1307 operands[0] = gen_lowpart (SImode, operands[0]);
1308 operands[4] = gen_highpart (SImode, operands[1]);
1309 operands[1] = gen_lowpart (SImode, operands[1]);
1310 operands[5] = GEN_INT (~0);
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_sesidi"
1318 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1319 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1320 (sign_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, %2, asr #31"
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 (minus:SI (match_dup 4)
1330 (ashiftrt:SI (match_dup 2)
1331 (const_int 31)))
1332 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1333 {
1334 operands[3] = gen_highpart (SImode, operands[0]);
1335 operands[0] = gen_lowpart (SImode, operands[0]);
1336 operands[4] = gen_highpart (SImode, operands[1]);
1337 operands[1] = gen_lowpart (SImode, operands[1]);
1338 }
1339 [(set_attr "conds" "clob")
1340 (set_attr "length" "8")
1341 (set_attr "type" "multiple")]
1342 )
1343
1344 (define_insn_and_split "*subdi_zesidi_di"
1345 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1346 (minus:DI (zero_extend:DI
1347 (match_operand:SI 2 "s_register_operand" "r,r"))
1348 (match_operand:DI 1 "s_register_operand" "0,r")))
1349 (clobber (reg:CC CC_REGNUM))]
1350 "TARGET_ARM"
1351 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1352 ; is equivalent to:
1353 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1354 "&& reload_completed"
1355 [(parallel [(set (reg:CC CC_REGNUM)
1356 (compare:CC (match_dup 2) (match_dup 1)))
1357 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1358 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1359 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1360 {
1361 operands[3] = gen_highpart (SImode, operands[0]);
1362 operands[0] = gen_lowpart (SImode, operands[0]);
1363 operands[4] = gen_highpart (SImode, operands[1]);
1364 operands[1] = gen_lowpart (SImode, operands[1]);
1365 }
1366 [(set_attr "conds" "clob")
1367 (set_attr "length" "8")
1368 (set_attr "type" "multiple")]
1369 )
1370
1371 (define_insn_and_split "*subdi_sesidi_di"
1372 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1373 (minus:DI (sign_extend:DI
1374 (match_operand:SI 2 "s_register_operand" "r,r"))
1375 (match_operand:DI 1 "s_register_operand" "0,r")))
1376 (clobber (reg:CC CC_REGNUM))]
1377 "TARGET_ARM"
1378 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1379 ; is equivalent to:
1380 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1381 "&& reload_completed"
1382 [(parallel [(set (reg:CC CC_REGNUM)
1383 (compare:CC (match_dup 2) (match_dup 1)))
1384 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1385 (set (match_dup 3) (minus:SI (minus:SI
1386 (ashiftrt:SI (match_dup 2)
1387 (const_int 31))
1388 (match_dup 4))
1389 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1390 {
1391 operands[3] = gen_highpart (SImode, operands[0]);
1392 operands[0] = gen_lowpart (SImode, operands[0]);
1393 operands[4] = gen_highpart (SImode, operands[1]);
1394 operands[1] = gen_lowpart (SImode, operands[1]);
1395 }
1396 [(set_attr "conds" "clob")
1397 (set_attr "length" "8")
1398 (set_attr "type" "multiple")]
1399 )
1400
1401 (define_insn_and_split "*subdi_zesidi_zesidi"
1402 [(set (match_operand:DI 0 "s_register_operand" "=r")
1403 (minus:DI (zero_extend:DI
1404 (match_operand:SI 1 "s_register_operand" "r"))
1405 (zero_extend:DI
1406 (match_operand:SI 2 "s_register_operand" "r"))))
1407 (clobber (reg:CC CC_REGNUM))]
1408 "TARGET_32BIT"
1409 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1410 "&& reload_completed"
1411 [(parallel [(set (reg:CC CC_REGNUM)
1412 (compare:CC (match_dup 1) (match_dup 2)))
1413 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1414 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1415 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1416 {
1417 operands[3] = gen_highpart (SImode, operands[0]);
1418 operands[0] = gen_lowpart (SImode, operands[0]);
1419 }
1420 [(set_attr "conds" "clob")
1421 (set_attr "length" "8")
1422 (set_attr "type" "multiple")]
1423 )
1424
1425 (define_expand "subsi3"
1426 [(set (match_operand:SI 0 "s_register_operand" "")
1427 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1428 (match_operand:SI 2 "s_register_operand" "")))]
1429 "TARGET_EITHER"
1430 "
1431 if (CONST_INT_P (operands[1]))
1432 {
1433 if (TARGET_32BIT)
1434 {
1435 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1436 operands[1] = force_reg (SImode, operands[1]);
1437 else
1438 {
1439 arm_split_constant (MINUS, SImode, NULL_RTX,
1440 INTVAL (operands[1]), operands[0],
1441 operands[2],
1442 optimize && can_create_pseudo_p ());
1443 DONE;
1444 }
1445 }
1446 else /* TARGET_THUMB1 */
1447 operands[1] = force_reg (SImode, operands[1]);
1448 }
1449 "
1450 )
1451
1452 ; ??? Check Thumb-2 split length
1453 (define_insn_and_split "*arm_subsi3_insn"
1454 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1455 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1456 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
1457 "TARGET_32BIT"
1458 "@
1459 sub%?\\t%0, %1, %2
1460 sub%?\\t%0, %2
1461 sub%?\\t%0, %1, %2
1462 rsb%?\\t%0, %2, %1
1463 rsb%?\\t%0, %2, %1
1464 sub%?\\t%0, %1, %2
1465 sub%?\\t%0, %1, %2
1466 sub%?\\t%0, %1, %2
1467 #"
1468 "&& (CONST_INT_P (operands[1])
1469 && !const_ok_for_arm (INTVAL (operands[1])))"
1470 [(clobber (const_int 0))]
1471 "
1472 arm_split_constant (MINUS, SImode, curr_insn,
1473 INTVAL (operands[1]), operands[0], operands[2], 0);
1474 DONE;
1475 "
1476 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1477 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
1478 (set_attr "predicable" "yes")
1479 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
1480 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
1481 )
1482
1483 (define_peephole2
1484 [(match_scratch:SI 3 "r")
1485 (set (match_operand:SI 0 "arm_general_register_operand" "")
1486 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1487 (match_operand:SI 2 "arm_general_register_operand" "")))]
1488 "TARGET_32BIT
1489 && !const_ok_for_arm (INTVAL (operands[1]))
1490 && const_ok_for_arm (~INTVAL (operands[1]))"
1491 [(set (match_dup 3) (match_dup 1))
1492 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1493 ""
1494 )
1495
1496 (define_insn "subsi3_compare0"
1497 [(set (reg:CC_NOOV CC_REGNUM)
1498 (compare:CC_NOOV
1499 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1500 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
1501 (const_int 0)))
1502 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1503 (minus:SI (match_dup 1) (match_dup 2)))]
1504 "TARGET_32BIT"
1505 "@
1506 subs%?\\t%0, %1, %2
1507 subs%?\\t%0, %1, %2
1508 rsbs%?\\t%0, %2, %1"
1509 [(set_attr "conds" "set")
1510 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1511 )
1512
1513 (define_insn "subsi3_compare"
1514 [(set (reg:CC CC_REGNUM)
1515 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1516 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1517 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1518 (minus:SI (match_dup 1) (match_dup 2)))]
1519 "TARGET_32BIT"
1520 "@
1521 subs%?\\t%0, %1, %2
1522 subs%?\\t%0, %1, %2
1523 rsbs%?\\t%0, %2, %1"
1524 [(set_attr "conds" "set")
1525 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1526 )
1527
1528 (define_expand "subsf3"
1529 [(set (match_operand:SF 0 "s_register_operand" "")
1530 (minus:SF (match_operand:SF 1 "s_register_operand" "")
1531 (match_operand:SF 2 "s_register_operand" "")))]
1532 "TARGET_32BIT && TARGET_HARD_FLOAT"
1533 "
1534 ")
1535
1536 (define_expand "subdf3"
1537 [(set (match_operand:DF 0 "s_register_operand" "")
1538 (minus:DF (match_operand:DF 1 "s_register_operand" "")
1539 (match_operand:DF 2 "s_register_operand" "")))]
1540 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1541 "
1542 ")
1543
1544 \f
1545 ;; Multiplication insns
1546
1547 (define_expand "mulhi3"
1548 [(set (match_operand:HI 0 "s_register_operand" "")
1549 (mult:HI (match_operand:HI 1 "s_register_operand" "")
1550 (match_operand:HI 2 "s_register_operand" "")))]
1551 "TARGET_DSP_MULTIPLY"
1552 "
1553 {
1554 rtx result = gen_reg_rtx (SImode);
1555 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1556 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1557 DONE;
1558 }"
1559 )
1560
1561 (define_expand "mulsi3"
1562 [(set (match_operand:SI 0 "s_register_operand" "")
1563 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1564 (match_operand:SI 1 "s_register_operand" "")))]
1565 "TARGET_EITHER"
1566 ""
1567 )
1568
1569 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1570 (define_insn "*arm_mulsi3"
1571 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1572 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1573 (match_operand:SI 1 "s_register_operand" "%0,r")))]
1574 "TARGET_32BIT && !arm_arch6"
1575 "mul%?\\t%0, %2, %1"
1576 [(set_attr "type" "mul")
1577 (set_attr "predicable" "yes")]
1578 )
1579
1580 (define_insn "*arm_mulsi3_v6"
1581 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1582 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1583 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
1584 "TARGET_32BIT && arm_arch6"
1585 "mul%?\\t%0, %1, %2"
1586 [(set_attr "type" "mul")
1587 (set_attr "predicable" "yes")
1588 (set_attr "arch" "t2,t2,*")
1589 (set_attr "length" "4")
1590 (set_attr "predicable_short_it" "yes,yes,no")]
1591 )
1592
1593 (define_insn "*mulsi3_compare0"
1594 [(set (reg:CC_NOOV CC_REGNUM)
1595 (compare:CC_NOOV (mult:SI
1596 (match_operand:SI 2 "s_register_operand" "r,r")
1597 (match_operand:SI 1 "s_register_operand" "%0,r"))
1598 (const_int 0)))
1599 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1600 (mult:SI (match_dup 2) (match_dup 1)))]
1601 "TARGET_ARM && !arm_arch6"
1602 "muls%?\\t%0, %2, %1"
1603 [(set_attr "conds" "set")
1604 (set_attr "type" "muls")]
1605 )
1606
1607 (define_insn "*mulsi3_compare0_v6"
1608 [(set (reg:CC_NOOV CC_REGNUM)
1609 (compare:CC_NOOV (mult:SI
1610 (match_operand:SI 2 "s_register_operand" "r")
1611 (match_operand:SI 1 "s_register_operand" "r"))
1612 (const_int 0)))
1613 (set (match_operand:SI 0 "s_register_operand" "=r")
1614 (mult:SI (match_dup 2) (match_dup 1)))]
1615 "TARGET_ARM && arm_arch6 && optimize_size"
1616 "muls%?\\t%0, %2, %1"
1617 [(set_attr "conds" "set")
1618 (set_attr "type" "muls")]
1619 )
1620
1621 (define_insn "*mulsi_compare0_scratch"
1622 [(set (reg:CC_NOOV CC_REGNUM)
1623 (compare:CC_NOOV (mult:SI
1624 (match_operand:SI 2 "s_register_operand" "r,r")
1625 (match_operand:SI 1 "s_register_operand" "%0,r"))
1626 (const_int 0)))
1627 (clobber (match_scratch:SI 0 "=&r,&r"))]
1628 "TARGET_ARM && !arm_arch6"
1629 "muls%?\\t%0, %2, %1"
1630 [(set_attr "conds" "set")
1631 (set_attr "type" "muls")]
1632 )
1633
1634 (define_insn "*mulsi_compare0_scratch_v6"
1635 [(set (reg:CC_NOOV CC_REGNUM)
1636 (compare:CC_NOOV (mult:SI
1637 (match_operand:SI 2 "s_register_operand" "r")
1638 (match_operand:SI 1 "s_register_operand" "r"))
1639 (const_int 0)))
1640 (clobber (match_scratch:SI 0 "=r"))]
1641 "TARGET_ARM && arm_arch6 && optimize_size"
1642 "muls%?\\t%0, %2, %1"
1643 [(set_attr "conds" "set")
1644 (set_attr "type" "muls")]
1645 )
1646
1647 ;; Unnamed templates to match MLA instruction.
1648
1649 (define_insn "*mulsi3addsi"
1650 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1651 (plus:SI
1652 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1653 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1654 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1655 "TARGET_32BIT && !arm_arch6"
1656 "mla%?\\t%0, %2, %1, %3"
1657 [(set_attr "type" "mla")
1658 (set_attr "predicable" "yes")]
1659 )
1660
1661 (define_insn "*mulsi3addsi_v6"
1662 [(set (match_operand:SI 0 "s_register_operand" "=r")
1663 (plus:SI
1664 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1665 (match_operand:SI 1 "s_register_operand" "r"))
1666 (match_operand:SI 3 "s_register_operand" "r")))]
1667 "TARGET_32BIT && arm_arch6"
1668 "mla%?\\t%0, %2, %1, %3"
1669 [(set_attr "type" "mla")
1670 (set_attr "predicable" "yes")
1671 (set_attr "predicable_short_it" "no")]
1672 )
1673
1674 (define_insn "*mulsi3addsi_compare0"
1675 [(set (reg:CC_NOOV CC_REGNUM)
1676 (compare:CC_NOOV
1677 (plus:SI (mult:SI
1678 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1679 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1680 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1681 (const_int 0)))
1682 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1683 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1684 (match_dup 3)))]
1685 "TARGET_ARM && arm_arch6"
1686 "mlas%?\\t%0, %2, %1, %3"
1687 [(set_attr "conds" "set")
1688 (set_attr "type" "mlas")]
1689 )
1690
1691 (define_insn "*mulsi3addsi_compare0_v6"
1692 [(set (reg:CC_NOOV CC_REGNUM)
1693 (compare:CC_NOOV
1694 (plus:SI (mult:SI
1695 (match_operand:SI 2 "s_register_operand" "r")
1696 (match_operand:SI 1 "s_register_operand" "r"))
1697 (match_operand:SI 3 "s_register_operand" "r"))
1698 (const_int 0)))
1699 (set (match_operand:SI 0 "s_register_operand" "=r")
1700 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1701 (match_dup 3)))]
1702 "TARGET_ARM && arm_arch6 && optimize_size"
1703 "mlas%?\\t%0, %2, %1, %3"
1704 [(set_attr "conds" "set")
1705 (set_attr "type" "mlas")]
1706 )
1707
1708 (define_insn "*mulsi3addsi_compare0_scratch"
1709 [(set (reg:CC_NOOV CC_REGNUM)
1710 (compare:CC_NOOV
1711 (plus:SI (mult:SI
1712 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1713 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1714 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1715 (const_int 0)))
1716 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1717 "TARGET_ARM && !arm_arch6"
1718 "mlas%?\\t%0, %2, %1, %3"
1719 [(set_attr "conds" "set")
1720 (set_attr "type" "mlas")]
1721 )
1722
1723 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1724 [(set (reg:CC_NOOV CC_REGNUM)
1725 (compare:CC_NOOV
1726 (plus:SI (mult:SI
1727 (match_operand:SI 2 "s_register_operand" "r")
1728 (match_operand:SI 1 "s_register_operand" "r"))
1729 (match_operand:SI 3 "s_register_operand" "r"))
1730 (const_int 0)))
1731 (clobber (match_scratch:SI 0 "=r"))]
1732 "TARGET_ARM && arm_arch6 && optimize_size"
1733 "mlas%?\\t%0, %2, %1, %3"
1734 [(set_attr "conds" "set")
1735 (set_attr "type" "mlas")]
1736 )
1737
1738 (define_insn "*mulsi3subsi"
1739 [(set (match_operand:SI 0 "s_register_operand" "=r")
1740 (minus:SI
1741 (match_operand:SI 3 "s_register_operand" "r")
1742 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1743 (match_operand:SI 1 "s_register_operand" "r"))))]
1744 "TARGET_32BIT && arm_arch_thumb2"
1745 "mls%?\\t%0, %2, %1, %3"
1746 [(set_attr "type" "mla")
1747 (set_attr "predicable" "yes")
1748 (set_attr "predicable_short_it" "no")]
1749 )
1750
1751 (define_expand "maddsidi4"
1752 [(set (match_operand:DI 0 "s_register_operand" "")
1753 (plus:DI
1754 (mult:DI
1755 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1756 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1757 (match_operand:DI 3 "s_register_operand" "")))]
1758 "TARGET_32BIT && arm_arch3m"
1759 "")
1760
1761 (define_insn "*mulsidi3adddi"
1762 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1763 (plus:DI
1764 (mult:DI
1765 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1766 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1767 (match_operand:DI 1 "s_register_operand" "0")))]
1768 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1769 "smlal%?\\t%Q0, %R0, %3, %2"
1770 [(set_attr "type" "smlal")
1771 (set_attr "predicable" "yes")]
1772 )
1773
1774 (define_insn "*mulsidi3adddi_v6"
1775 [(set (match_operand:DI 0 "s_register_operand" "=r")
1776 (plus:DI
1777 (mult:DI
1778 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1779 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1780 (match_operand:DI 1 "s_register_operand" "0")))]
1781 "TARGET_32BIT && arm_arch6"
1782 "smlal%?\\t%Q0, %R0, %3, %2"
1783 [(set_attr "type" "smlal")
1784 (set_attr "predicable" "yes")
1785 (set_attr "predicable_short_it" "no")]
1786 )
1787
1788 ;; 32x32->64 widening multiply.
1789 ;; As with mulsi3, the only difference between the v3-5 and v6+
1790 ;; versions of these patterns is the requirement that the output not
1791 ;; overlap the inputs, but that still means we have to have a named
1792 ;; expander and two different starred insns.
1793
1794 (define_expand "mulsidi3"
1795 [(set (match_operand:DI 0 "s_register_operand" "")
1796 (mult:DI
1797 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1798 (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1799 "TARGET_32BIT && arm_arch3m"
1800 ""
1801 )
1802
1803 (define_insn "*mulsidi3_nov6"
1804 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1805 (mult:DI
1806 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1807 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1808 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1809 "smull%?\\t%Q0, %R0, %1, %2"
1810 [(set_attr "type" "smull")
1811 (set_attr "predicable" "yes")]
1812 )
1813
1814 (define_insn "*mulsidi3_v6"
1815 [(set (match_operand:DI 0 "s_register_operand" "=r")
1816 (mult:DI
1817 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1818 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1819 "TARGET_32BIT && arm_arch6"
1820 "smull%?\\t%Q0, %R0, %1, %2"
1821 [(set_attr "type" "smull")
1822 (set_attr "predicable" "yes")
1823 (set_attr "predicable_short_it" "no")]
1824 )
1825
1826 (define_expand "umulsidi3"
1827 [(set (match_operand:DI 0 "s_register_operand" "")
1828 (mult:DI
1829 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1830 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1831 "TARGET_32BIT && arm_arch3m"
1832 ""
1833 )
1834
1835 (define_insn "*umulsidi3_nov6"
1836 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1837 (mult:DI
1838 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1839 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1840 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1841 "umull%?\\t%Q0, %R0, %1, %2"
1842 [(set_attr "type" "umull")
1843 (set_attr "predicable" "yes")]
1844 )
1845
1846 (define_insn "*umulsidi3_v6"
1847 [(set (match_operand:DI 0 "s_register_operand" "=r")
1848 (mult:DI
1849 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1850 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1851 "TARGET_32BIT && arm_arch6"
1852 "umull%?\\t%Q0, %R0, %1, %2"
1853 [(set_attr "type" "umull")
1854 (set_attr "predicable" "yes")
1855 (set_attr "predicable_short_it" "no")]
1856 )
1857
1858 (define_expand "umaddsidi4"
1859 [(set (match_operand:DI 0 "s_register_operand" "")
1860 (plus:DI
1861 (mult:DI
1862 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1863 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1864 (match_operand:DI 3 "s_register_operand" "")))]
1865 "TARGET_32BIT && arm_arch3m"
1866 "")
1867
1868 (define_insn "*umulsidi3adddi"
1869 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1870 (plus:DI
1871 (mult:DI
1872 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1873 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1874 (match_operand:DI 1 "s_register_operand" "0")))]
1875 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1876 "umlal%?\\t%Q0, %R0, %3, %2"
1877 [(set_attr "type" "umlal")
1878 (set_attr "predicable" "yes")]
1879 )
1880
1881 (define_insn "*umulsidi3adddi_v6"
1882 [(set (match_operand:DI 0 "s_register_operand" "=r")
1883 (plus:DI
1884 (mult:DI
1885 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1886 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1887 (match_operand:DI 1 "s_register_operand" "0")))]
1888 "TARGET_32BIT && arm_arch6"
1889 "umlal%?\\t%Q0, %R0, %3, %2"
1890 [(set_attr "type" "umlal")
1891 (set_attr "predicable" "yes")
1892 (set_attr "predicable_short_it" "no")]
1893 )
1894
1895 (define_expand "smulsi3_highpart"
1896 [(parallel
1897 [(set (match_operand:SI 0 "s_register_operand" "")
1898 (truncate:SI
1899 (lshiftrt:DI
1900 (mult:DI
1901 (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1902 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1903 (const_int 32))))
1904 (clobber (match_scratch:SI 3 ""))])]
1905 "TARGET_32BIT && arm_arch3m"
1906 ""
1907 )
1908
1909 (define_insn "*smulsi3_highpart_nov6"
1910 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1911 (truncate:SI
1912 (lshiftrt:DI
1913 (mult:DI
1914 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1915 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1916 (const_int 32))))
1917 (clobber (match_scratch:SI 3 "=&r,&r"))]
1918 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1919 "smull%?\\t%3, %0, %2, %1"
1920 [(set_attr "type" "smull")
1921 (set_attr "predicable" "yes")]
1922 )
1923
1924 (define_insn "*smulsi3_highpart_v6"
1925 [(set (match_operand:SI 0 "s_register_operand" "=r")
1926 (truncate:SI
1927 (lshiftrt:DI
1928 (mult:DI
1929 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1930 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1931 (const_int 32))))
1932 (clobber (match_scratch:SI 3 "=r"))]
1933 "TARGET_32BIT && arm_arch6"
1934 "smull%?\\t%3, %0, %2, %1"
1935 [(set_attr "type" "smull")
1936 (set_attr "predicable" "yes")
1937 (set_attr "predicable_short_it" "no")]
1938 )
1939
1940 (define_expand "umulsi3_highpart"
1941 [(parallel
1942 [(set (match_operand:SI 0 "s_register_operand" "")
1943 (truncate:SI
1944 (lshiftrt:DI
1945 (mult:DI
1946 (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1947 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1948 (const_int 32))))
1949 (clobber (match_scratch:SI 3 ""))])]
1950 "TARGET_32BIT && arm_arch3m"
1951 ""
1952 )
1953
1954 (define_insn "*umulsi3_highpart_nov6"
1955 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1956 (truncate:SI
1957 (lshiftrt:DI
1958 (mult:DI
1959 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1960 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1961 (const_int 32))))
1962 (clobber (match_scratch:SI 3 "=&r,&r"))]
1963 "TARGET_32BIT && arm_arch3m && !arm_arch6"
1964 "umull%?\\t%3, %0, %2, %1"
1965 [(set_attr "type" "umull")
1966 (set_attr "predicable" "yes")]
1967 )
1968
1969 (define_insn "*umulsi3_highpart_v6"
1970 [(set (match_operand:SI 0 "s_register_operand" "=r")
1971 (truncate:SI
1972 (lshiftrt:DI
1973 (mult:DI
1974 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1975 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1976 (const_int 32))))
1977 (clobber (match_scratch:SI 3 "=r"))]
1978 "TARGET_32BIT && arm_arch6"
1979 "umull%?\\t%3, %0, %2, %1"
1980 [(set_attr "type" "umull")
1981 (set_attr "predicable" "yes")
1982 (set_attr "predicable_short_it" "no")]
1983 )
1984
1985 (define_insn "mulhisi3"
1986 [(set (match_operand:SI 0 "s_register_operand" "=r")
1987 (mult:SI (sign_extend:SI
1988 (match_operand:HI 1 "s_register_operand" "%r"))
1989 (sign_extend:SI
1990 (match_operand:HI 2 "s_register_operand" "r"))))]
1991 "TARGET_DSP_MULTIPLY"
1992 "smulbb%?\\t%0, %1, %2"
1993 [(set_attr "type" "smulxy")
1994 (set_attr "predicable" "yes")]
1995 )
1996
1997 (define_insn "*mulhisi3tb"
1998 [(set (match_operand:SI 0 "s_register_operand" "=r")
1999 (mult:SI (ashiftrt:SI
2000 (match_operand:SI 1 "s_register_operand" "r")
2001 (const_int 16))
2002 (sign_extend:SI
2003 (match_operand:HI 2 "s_register_operand" "r"))))]
2004 "TARGET_DSP_MULTIPLY"
2005 "smultb%?\\t%0, %1, %2"
2006 [(set_attr "type" "smulxy")
2007 (set_attr "predicable" "yes")
2008 (set_attr "predicable_short_it" "no")]
2009 )
2010
2011 (define_insn "*mulhisi3bt"
2012 [(set (match_operand:SI 0 "s_register_operand" "=r")
2013 (mult:SI (sign_extend:SI
2014 (match_operand:HI 1 "s_register_operand" "r"))
2015 (ashiftrt:SI
2016 (match_operand:SI 2 "s_register_operand" "r")
2017 (const_int 16))))]
2018 "TARGET_DSP_MULTIPLY"
2019 "smulbt%?\\t%0, %1, %2"
2020 [(set_attr "type" "smulxy")
2021 (set_attr "predicable" "yes")
2022 (set_attr "predicable_short_it" "no")]
2023 )
2024
2025 (define_insn "*mulhisi3tt"
2026 [(set (match_operand:SI 0 "s_register_operand" "=r")
2027 (mult:SI (ashiftrt:SI
2028 (match_operand:SI 1 "s_register_operand" "r")
2029 (const_int 16))
2030 (ashiftrt:SI
2031 (match_operand:SI 2 "s_register_operand" "r")
2032 (const_int 16))))]
2033 "TARGET_DSP_MULTIPLY"
2034 "smultt%?\\t%0, %1, %2"
2035 [(set_attr "type" "smulxy")
2036 (set_attr "predicable" "yes")
2037 (set_attr "predicable_short_it" "no")]
2038 )
2039
2040 (define_insn "maddhisi4"
2041 [(set (match_operand:SI 0 "s_register_operand" "=r")
2042 (plus:SI (mult:SI (sign_extend:SI
2043 (match_operand:HI 1 "s_register_operand" "r"))
2044 (sign_extend:SI
2045 (match_operand:HI 2 "s_register_operand" "r")))
2046 (match_operand:SI 3 "s_register_operand" "r")))]
2047 "TARGET_DSP_MULTIPLY"
2048 "smlabb%?\\t%0, %1, %2, %3"
2049 [(set_attr "type" "smlaxy")
2050 (set_attr "predicable" "yes")
2051 (set_attr "predicable_short_it" "no")]
2052 )
2053
2054 ;; Note: there is no maddhisi4ibt because this one is canonical form
2055 (define_insn "*maddhisi4tb"
2056 [(set (match_operand:SI 0 "s_register_operand" "=r")
2057 (plus:SI (mult:SI (ashiftrt:SI
2058 (match_operand:SI 1 "s_register_operand" "r")
2059 (const_int 16))
2060 (sign_extend:SI
2061 (match_operand:HI 2 "s_register_operand" "r")))
2062 (match_operand:SI 3 "s_register_operand" "r")))]
2063 "TARGET_DSP_MULTIPLY"
2064 "smlatb%?\\t%0, %1, %2, %3"
2065 [(set_attr "type" "smlaxy")
2066 (set_attr "predicable" "yes")
2067 (set_attr "predicable_short_it" "no")]
2068 )
2069
2070 (define_insn "*maddhisi4tt"
2071 [(set (match_operand:SI 0 "s_register_operand" "=r")
2072 (plus:SI (mult:SI (ashiftrt:SI
2073 (match_operand:SI 1 "s_register_operand" "r")
2074 (const_int 16))
2075 (ashiftrt:SI
2076 (match_operand:SI 2 "s_register_operand" "r")
2077 (const_int 16)))
2078 (match_operand:SI 3 "s_register_operand" "r")))]
2079 "TARGET_DSP_MULTIPLY"
2080 "smlatt%?\\t%0, %1, %2, %3"
2081 [(set_attr "type" "smlaxy")
2082 (set_attr "predicable" "yes")
2083 (set_attr "predicable_short_it" "no")]
2084 )
2085
2086 (define_insn "maddhidi4"
2087 [(set (match_operand:DI 0 "s_register_operand" "=r")
2088 (plus:DI
2089 (mult:DI (sign_extend:DI
2090 (match_operand:HI 1 "s_register_operand" "r"))
2091 (sign_extend:DI
2092 (match_operand:HI 2 "s_register_operand" "r")))
2093 (match_operand:DI 3 "s_register_operand" "0")))]
2094 "TARGET_DSP_MULTIPLY"
2095 "smlalbb%?\\t%Q0, %R0, %1, %2"
2096 [(set_attr "type" "smlalxy")
2097 (set_attr "predicable" "yes")
2098 (set_attr "predicable_short_it" "no")])
2099
2100 ;; Note: there is no maddhidi4ibt because this one is canonical form
2101 (define_insn "*maddhidi4tb"
2102 [(set (match_operand:DI 0 "s_register_operand" "=r")
2103 (plus:DI
2104 (mult:DI (sign_extend:DI
2105 (ashiftrt:SI
2106 (match_operand:SI 1 "s_register_operand" "r")
2107 (const_int 16)))
2108 (sign_extend:DI
2109 (match_operand:HI 2 "s_register_operand" "r")))
2110 (match_operand:DI 3 "s_register_operand" "0")))]
2111 "TARGET_DSP_MULTIPLY"
2112 "smlaltb%?\\t%Q0, %R0, %1, %2"
2113 [(set_attr "type" "smlalxy")
2114 (set_attr "predicable" "yes")
2115 (set_attr "predicable_short_it" "no")])
2116
2117 (define_insn "*maddhidi4tt"
2118 [(set (match_operand:DI 0 "s_register_operand" "=r")
2119 (plus:DI
2120 (mult:DI (sign_extend:DI
2121 (ashiftrt:SI
2122 (match_operand:SI 1 "s_register_operand" "r")
2123 (const_int 16)))
2124 (sign_extend:DI
2125 (ashiftrt:SI
2126 (match_operand:SI 2 "s_register_operand" "r")
2127 (const_int 16))))
2128 (match_operand:DI 3 "s_register_operand" "0")))]
2129 "TARGET_DSP_MULTIPLY"
2130 "smlaltt%?\\t%Q0, %R0, %1, %2"
2131 [(set_attr "type" "smlalxy")
2132 (set_attr "predicable" "yes")
2133 (set_attr "predicable_short_it" "no")])
2134
2135 (define_expand "mulsf3"
2136 [(set (match_operand:SF 0 "s_register_operand" "")
2137 (mult:SF (match_operand:SF 1 "s_register_operand" "")
2138 (match_operand:SF 2 "s_register_operand" "")))]
2139 "TARGET_32BIT && TARGET_HARD_FLOAT"
2140 "
2141 ")
2142
2143 (define_expand "muldf3"
2144 [(set (match_operand:DF 0 "s_register_operand" "")
2145 (mult:DF (match_operand:DF 1 "s_register_operand" "")
2146 (match_operand:DF 2 "s_register_operand" "")))]
2147 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
2148 "
2149 ")
2150 \f
2151 ;; Division insns
2152
2153 (define_expand "divsf3"
2154 [(set (match_operand:SF 0 "s_register_operand" "")
2155 (div:SF (match_operand:SF 1 "s_register_operand" "")
2156 (match_operand:SF 2 "s_register_operand" "")))]
2157 "TARGET_32BIT && TARGET_HARD_FLOAT"
2158 "")
2159
2160 (define_expand "divdf3"
2161 [(set (match_operand:DF 0 "s_register_operand" "")
2162 (div:DF (match_operand:DF 1 "s_register_operand" "")
2163 (match_operand:DF 2 "s_register_operand" "")))]
2164 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
2165 "")
2166 \f
2167 ;; Boolean and,ior,xor insns
2168
2169 ;; Split up double word logical operations
2170
2171 ;; Split up simple DImode logical operations. Simply perform the logical
2172 ;; operation on the upper and lower halves of the registers.
2173 (define_split
2174 [(set (match_operand:DI 0 "s_register_operand" "")
2175 (match_operator:DI 6 "logical_binary_operator"
2176 [(match_operand:DI 1 "s_register_operand" "")
2177 (match_operand:DI 2 "s_register_operand" "")]))]
2178 "TARGET_32BIT && reload_completed
2179 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2180 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2181 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2182 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2183 "
2184 {
2185 operands[3] = gen_highpart (SImode, operands[0]);
2186 operands[0] = gen_lowpart (SImode, operands[0]);
2187 operands[4] = gen_highpart (SImode, operands[1]);
2188 operands[1] = gen_lowpart (SImode, operands[1]);
2189 operands[5] = gen_highpart (SImode, operands[2]);
2190 operands[2] = gen_lowpart (SImode, operands[2]);
2191 }"
2192 )
2193
2194 (define_split
2195 [(set (match_operand:DI 0 "s_register_operand" "")
2196 (match_operator:DI 6 "logical_binary_operator"
2197 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2198 (match_operand:DI 1 "s_register_operand" "")]))]
2199 "TARGET_32BIT && reload_completed"
2200 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2201 (set (match_dup 3) (match_op_dup:SI 6
2202 [(ashiftrt:SI (match_dup 2) (const_int 31))
2203 (match_dup 4)]))]
2204 "
2205 {
2206 operands[3] = gen_highpart (SImode, operands[0]);
2207 operands[0] = gen_lowpart (SImode, operands[0]);
2208 operands[4] = gen_highpart (SImode, operands[1]);
2209 operands[1] = gen_lowpart (SImode, operands[1]);
2210 operands[5] = gen_highpart (SImode, operands[2]);
2211 operands[2] = gen_lowpart (SImode, operands[2]);
2212 }"
2213 )
2214
2215 ;; The zero extend of operand 2 means we can just copy the high part of
2216 ;; operand1 into operand0.
2217 (define_split
2218 [(set (match_operand:DI 0 "s_register_operand" "")
2219 (ior:DI
2220 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2221 (match_operand:DI 1 "s_register_operand" "")))]
2222 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2223 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2224 (set (match_dup 3) (match_dup 4))]
2225 "
2226 {
2227 operands[4] = gen_highpart (SImode, operands[1]);
2228 operands[3] = gen_highpart (SImode, operands[0]);
2229 operands[0] = gen_lowpart (SImode, operands[0]);
2230 operands[1] = gen_lowpart (SImode, operands[1]);
2231 }"
2232 )
2233
2234 ;; The zero extend of operand 2 means we can just copy the high part of
2235 ;; operand1 into operand0.
2236 (define_split
2237 [(set (match_operand:DI 0 "s_register_operand" "")
2238 (xor:DI
2239 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2240 (match_operand:DI 1 "s_register_operand" "")))]
2241 "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2242 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2243 (set (match_dup 3) (match_dup 4))]
2244 "
2245 {
2246 operands[4] = gen_highpart (SImode, operands[1]);
2247 operands[3] = gen_highpart (SImode, operands[0]);
2248 operands[0] = gen_lowpart (SImode, operands[0]);
2249 operands[1] = gen_lowpart (SImode, operands[1]);
2250 }"
2251 )
2252
2253 (define_expand "anddi3"
2254 [(set (match_operand:DI 0 "s_register_operand" "")
2255 (and:DI (match_operand:DI 1 "s_register_operand" "")
2256 (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2257 "TARGET_32BIT"
2258 ""
2259 )
2260
2261 (define_insn_and_split "*anddi3_insn"
2262 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2263 (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2264 (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
2265 "TARGET_32BIT && !TARGET_IWMMXT"
2266 {
2267 switch (which_alternative)
2268 {
2269 case 0: /* fall through */
2270 case 6: return "vand\t%P0, %P1, %P2";
2271 case 1: /* fall through */
2272 case 7: return neon_output_logic_immediate ("vand", &operands[2],
2273 DImode, 1, VALID_NEON_QREG_MODE (DImode));
2274 case 2:
2275 case 3:
2276 case 4:
2277 case 5: /* fall through */
2278 return "#";
2279 default: gcc_unreachable ();
2280 }
2281 }
2282 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2283 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2284 [(set (match_dup 3) (match_dup 4))
2285 (set (match_dup 5) (match_dup 6))]
2286 "
2287 {
2288 operands[3] = gen_lowpart (SImode, operands[0]);
2289 operands[5] = gen_highpart (SImode, operands[0]);
2290
2291 operands[4] = simplify_gen_binary (AND, SImode,
2292 gen_lowpart (SImode, operands[1]),
2293 gen_lowpart (SImode, operands[2]));
2294 operands[6] = simplify_gen_binary (AND, SImode,
2295 gen_highpart (SImode, operands[1]),
2296 gen_highpart_mode (SImode, DImode, operands[2]));
2297
2298 }"
2299 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2300 multiple,multiple,neon_logic,neon_logic")
2301 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
2302 avoid_neon_for_64bits,avoid_neon_for_64bits")
2303 (set_attr "length" "*,*,8,8,8,8,*,*")
2304 ]
2305 )
2306
2307 (define_insn_and_split "*anddi_zesidi_di"
2308 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2309 (and:DI (zero_extend:DI
2310 (match_operand:SI 2 "s_register_operand" "r,r"))
2311 (match_operand:DI 1 "s_register_operand" "0,r")))]
2312 "TARGET_32BIT"
2313 "#"
2314 "TARGET_32BIT && reload_completed"
2315 ; The zero extend of operand 2 clears the high word of the output
2316 ; operand.
2317 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2318 (set (match_dup 3) (const_int 0))]
2319 "
2320 {
2321 operands[3] = gen_highpart (SImode, operands[0]);
2322 operands[0] = gen_lowpart (SImode, operands[0]);
2323 operands[1] = gen_lowpart (SImode, operands[1]);
2324 }"
2325 [(set_attr "length" "8")
2326 (set_attr "type" "multiple")]
2327 )
2328
2329 (define_insn "*anddi_sesdi_di"
2330 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2331 (and:DI (sign_extend:DI
2332 (match_operand:SI 2 "s_register_operand" "r,r"))
2333 (match_operand:DI 1 "s_register_operand" "0,r")))]
2334 "TARGET_32BIT"
2335 "#"
2336 [(set_attr "length" "8")
2337 (set_attr "type" "multiple")]
2338 )
2339
2340 (define_expand "andsi3"
2341 [(set (match_operand:SI 0 "s_register_operand" "")
2342 (and:SI (match_operand:SI 1 "s_register_operand" "")
2343 (match_operand:SI 2 "reg_or_int_operand" "")))]
2344 "TARGET_EITHER"
2345 "
2346 if (TARGET_32BIT)
2347 {
2348 if (CONST_INT_P (operands[2]))
2349 {
2350 if (INTVAL (operands[2]) == 255 && arm_arch6)
2351 {
2352 operands[1] = convert_to_mode (QImode, operands[1], 1);
2353 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2354 operands[1]));
2355 DONE;
2356 }
2357 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2358 operands[2] = force_reg (SImode, operands[2]);
2359 else
2360 {
2361 arm_split_constant (AND, SImode, NULL_RTX,
2362 INTVAL (operands[2]), operands[0],
2363 operands[1],
2364 optimize && can_create_pseudo_p ());
2365
2366 DONE;
2367 }
2368 }
2369 }
2370 else /* TARGET_THUMB1 */
2371 {
2372 if (!CONST_INT_P (operands[2]))
2373 {
2374 rtx tmp = force_reg (SImode, operands[2]);
2375 if (rtx_equal_p (operands[0], operands[1]))
2376 operands[2] = tmp;
2377 else
2378 {
2379 operands[2] = operands[1];
2380 operands[1] = tmp;
2381 }
2382 }
2383 else
2384 {
2385 int i;
2386
2387 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2388 {
2389 operands[2] = force_reg (SImode,
2390 GEN_INT (~INTVAL (operands[2])));
2391
2392 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2393
2394 DONE;
2395 }
2396
2397 for (i = 9; i <= 31; i++)
2398 {
2399 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
2400 {
2401 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2402 const0_rtx));
2403 DONE;
2404 }
2405 else if ((HOST_WIDE_INT_1 << i) - 1
2406 == ~INTVAL (operands[2]))
2407 {
2408 rtx shift = GEN_INT (i);
2409 rtx reg = gen_reg_rtx (SImode);
2410
2411 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2412 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2413
2414 DONE;
2415 }
2416 }
2417
2418 operands[2] = force_reg (SImode, operands[2]);
2419 }
2420 }
2421 "
2422 )
2423
2424 ; ??? Check split length for Thumb-2
2425 (define_insn_and_split "*arm_andsi3_insn"
2426 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2427 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2428 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
2429 "TARGET_32BIT"
2430 "@
2431 and%?\\t%0, %1, %2
2432 and%?\\t%0, %1, %2
2433 bic%?\\t%0, %1, #%B2
2434 and%?\\t%0, %1, %2
2435 #"
2436 "TARGET_32BIT
2437 && CONST_INT_P (operands[2])
2438 && !(const_ok_for_arm (INTVAL (operands[2]))
2439 || const_ok_for_arm (~INTVAL (operands[2])))"
2440 [(clobber (const_int 0))]
2441 "
2442 arm_split_constant (AND, SImode, curr_insn,
2443 INTVAL (operands[2]), operands[0], operands[1], 0);
2444 DONE;
2445 "
2446 [(set_attr "length" "4,4,4,4,16")
2447 (set_attr "predicable" "yes")
2448 (set_attr "predicable_short_it" "no,yes,no,no,no")
2449 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
2450 )
2451
2452 (define_insn "*andsi3_compare0"
2453 [(set (reg:CC_NOOV CC_REGNUM)
2454 (compare:CC_NOOV
2455 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2456 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
2457 (const_int 0)))
2458 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2459 (and:SI (match_dup 1) (match_dup 2)))]
2460 "TARGET_32BIT"
2461 "@
2462 ands%?\\t%0, %1, %2
2463 bics%?\\t%0, %1, #%B2
2464 ands%?\\t%0, %1, %2"
2465 [(set_attr "conds" "set")
2466 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2467 )
2468
2469 (define_insn "*andsi3_compare0_scratch"
2470 [(set (reg:CC_NOOV CC_REGNUM)
2471 (compare:CC_NOOV
2472 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2473 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
2474 (const_int 0)))
2475 (clobber (match_scratch:SI 2 "=X,r,X"))]
2476 "TARGET_32BIT"
2477 "@
2478 tst%?\\t%0, %1
2479 bics%?\\t%2, %0, #%B1
2480 tst%?\\t%0, %1"
2481 [(set_attr "conds" "set")
2482 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2483 )
2484
2485 (define_insn "*zeroextractsi_compare0_scratch"
2486 [(set (reg:CC_NOOV CC_REGNUM)
2487 (compare:CC_NOOV (zero_extract:SI
2488 (match_operand:SI 0 "s_register_operand" "r")
2489 (match_operand 1 "const_int_operand" "n")
2490 (match_operand 2 "const_int_operand" "n"))
2491 (const_int 0)))]
2492 "TARGET_32BIT
2493 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2494 && INTVAL (operands[1]) > 0
2495 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2496 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2497 "*
2498 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2499 << INTVAL (operands[2]));
2500 output_asm_insn (\"tst%?\\t%0, %1\", operands);
2501 return \"\";
2502 "
2503 [(set_attr "conds" "set")
2504 (set_attr "predicable" "yes")
2505 (set_attr "predicable_short_it" "no")
2506 (set_attr "type" "logics_imm")]
2507 )
2508
2509 (define_insn_and_split "*ne_zeroextractsi"
2510 [(set (match_operand:SI 0 "s_register_operand" "=r")
2511 (ne:SI (zero_extract:SI
2512 (match_operand:SI 1 "s_register_operand" "r")
2513 (match_operand:SI 2 "const_int_operand" "n")
2514 (match_operand:SI 3 "const_int_operand" "n"))
2515 (const_int 0)))
2516 (clobber (reg:CC CC_REGNUM))]
2517 "TARGET_32BIT
2518 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2519 && INTVAL (operands[2]) > 0
2520 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2521 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2522 "#"
2523 "TARGET_32BIT
2524 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2525 && INTVAL (operands[2]) > 0
2526 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2527 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2528 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2529 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2530 (const_int 0)))
2531 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2532 (set (match_dup 0)
2533 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2534 (match_dup 0) (const_int 1)))]
2535 "
2536 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2537 << INTVAL (operands[3]));
2538 "
2539 [(set_attr "conds" "clob")
2540 (set (attr "length")
2541 (if_then_else (eq_attr "is_thumb" "yes")
2542 (const_int 12)
2543 (const_int 8)))
2544 (set_attr "type" "multiple")]
2545 )
2546
2547 (define_insn_and_split "*ne_zeroextractsi_shifted"
2548 [(set (match_operand:SI 0 "s_register_operand" "=r")
2549 (ne:SI (zero_extract:SI
2550 (match_operand:SI 1 "s_register_operand" "r")
2551 (match_operand:SI 2 "const_int_operand" "n")
2552 (const_int 0))
2553 (const_int 0)))
2554 (clobber (reg:CC CC_REGNUM))]
2555 "TARGET_ARM"
2556 "#"
2557 "TARGET_ARM"
2558 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2559 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2560 (const_int 0)))
2561 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2562 (set (match_dup 0)
2563 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2564 (match_dup 0) (const_int 1)))]
2565 "
2566 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2567 "
2568 [(set_attr "conds" "clob")
2569 (set_attr "length" "8")
2570 (set_attr "type" "multiple")]
2571 )
2572
2573 (define_insn_and_split "*ite_ne_zeroextractsi"
2574 [(set (match_operand:SI 0 "s_register_operand" "=r")
2575 (if_then_else:SI (ne (zero_extract:SI
2576 (match_operand:SI 1 "s_register_operand" "r")
2577 (match_operand:SI 2 "const_int_operand" "n")
2578 (match_operand:SI 3 "const_int_operand" "n"))
2579 (const_int 0))
2580 (match_operand:SI 4 "arm_not_operand" "rIK")
2581 (const_int 0)))
2582 (clobber (reg:CC CC_REGNUM))]
2583 "TARGET_ARM
2584 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2585 && INTVAL (operands[2]) > 0
2586 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2587 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2588 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2589 "#"
2590 "TARGET_ARM
2591 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2592 && INTVAL (operands[2]) > 0
2593 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2594 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2595 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2596 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2597 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2598 (const_int 0)))
2599 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2600 (set (match_dup 0)
2601 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2602 (match_dup 0) (match_dup 4)))]
2603 "
2604 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2605 << INTVAL (operands[3]));
2606 "
2607 [(set_attr "conds" "clob")
2608 (set_attr "length" "8")
2609 (set_attr "type" "multiple")]
2610 )
2611
2612 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2613 [(set (match_operand:SI 0 "s_register_operand" "=r")
2614 (if_then_else:SI (ne (zero_extract:SI
2615 (match_operand:SI 1 "s_register_operand" "r")
2616 (match_operand:SI 2 "const_int_operand" "n")
2617 (const_int 0))
2618 (const_int 0))
2619 (match_operand:SI 3 "arm_not_operand" "rIK")
2620 (const_int 0)))
2621 (clobber (reg:CC CC_REGNUM))]
2622 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2623 "#"
2624 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2625 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2626 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2627 (const_int 0)))
2628 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2629 (set (match_dup 0)
2630 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2631 (match_dup 0) (match_dup 3)))]
2632 "
2633 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2634 "
2635 [(set_attr "conds" "clob")
2636 (set_attr "length" "8")
2637 (set_attr "type" "multiple")]
2638 )
2639
2640 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2641 (define_split
2642 [(set (match_operand:SI 0 "s_register_operand" "")
2643 (match_operator:SI 1 "shiftable_operator"
2644 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2645 (match_operand:SI 3 "const_int_operand" "")
2646 (match_operand:SI 4 "const_int_operand" ""))
2647 (match_operand:SI 5 "s_register_operand" "")]))
2648 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2649 "TARGET_ARM"
2650 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2651 (set (match_dup 0)
2652 (match_op_dup 1
2653 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2654 (match_dup 5)]))]
2655 "{
2656 HOST_WIDE_INT temp = INTVAL (operands[3]);
2657
2658 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2659 operands[4] = GEN_INT (32 - temp);
2660 }"
2661 )
2662
2663 (define_split
2664 [(set (match_operand:SI 0 "s_register_operand" "")
2665 (match_operator:SI 1 "shiftable_operator"
2666 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2667 (match_operand:SI 3 "const_int_operand" "")
2668 (match_operand:SI 4 "const_int_operand" ""))
2669 (match_operand:SI 5 "s_register_operand" "")]))
2670 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2671 "TARGET_ARM"
2672 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2673 (set (match_dup 0)
2674 (match_op_dup 1
2675 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2676 (match_dup 5)]))]
2677 "{
2678 HOST_WIDE_INT temp = INTVAL (operands[3]);
2679
2680 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2681 operands[4] = GEN_INT (32 - temp);
2682 }"
2683 )
2684
2685 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
2686 ;;; represented by the bitfield, then this will produce incorrect results.
2687 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
2688 ;;; which have a real bit-field insert instruction, the truncation happens
2689 ;;; in the bit-field insert instruction itself. Since arm does not have a
2690 ;;; bit-field insert instruction, we would have to emit code here to truncate
2691 ;;; the value before we insert. This loses some of the advantage of having
2692 ;;; this insv pattern, so this pattern needs to be reevalutated.
2693
2694 (define_expand "insv"
2695 [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2696 (match_operand 1 "general_operand" "")
2697 (match_operand 2 "general_operand" ""))
2698 (match_operand 3 "reg_or_int_operand" ""))]
2699 "TARGET_ARM || arm_arch_thumb2"
2700 "
2701 {
2702 int start_bit = INTVAL (operands[2]);
2703 int width = INTVAL (operands[1]);
2704 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
2705 rtx target, subtarget;
2706
2707 if (arm_arch_thumb2)
2708 {
2709 if (unaligned_access && MEM_P (operands[0])
2710 && s_register_operand (operands[3], GET_MODE (operands[3]))
2711 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
2712 {
2713 rtx base_addr;
2714
2715 if (BYTES_BIG_ENDIAN)
2716 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2717 - start_bit;
2718
2719 if (width == 32)
2720 {
2721 base_addr = adjust_address (operands[0], SImode,
2722 start_bit / BITS_PER_UNIT);
2723 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
2724 }
2725 else
2726 {
2727 rtx tmp = gen_reg_rtx (HImode);
2728
2729 base_addr = adjust_address (operands[0], HImode,
2730 start_bit / BITS_PER_UNIT);
2731 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2732 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2733 }
2734 DONE;
2735 }
2736 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
2737 {
2738 bool use_bfi = TRUE;
2739
2740 if (CONST_INT_P (operands[3]))
2741 {
2742 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2743
2744 if (val == 0)
2745 {
2746 emit_insn (gen_insv_zero (operands[0], operands[1],
2747 operands[2]));
2748 DONE;
2749 }
2750
2751 /* See if the set can be done with a single orr instruction. */
2752 if (val == mask && const_ok_for_arm (val << start_bit))
2753 use_bfi = FALSE;
2754 }
2755
2756 if (use_bfi)
2757 {
2758 if (!REG_P (operands[3]))
2759 operands[3] = force_reg (SImode, operands[3]);
2760
2761 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2762 operands[3]));
2763 DONE;
2764 }
2765 }
2766 else
2767 FAIL;
2768 }
2769
2770 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2771 FAIL;
2772
2773 target = copy_rtx (operands[0]);
2774 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2775 subreg as the final target. */
2776 if (GET_CODE (target) == SUBREG)
2777 {
2778 subtarget = gen_reg_rtx (SImode);
2779 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2780 < GET_MODE_SIZE (SImode))
2781 target = SUBREG_REG (target);
2782 }
2783 else
2784 subtarget = target;
2785
2786 if (CONST_INT_P (operands[3]))
2787 {
2788 /* Since we are inserting a known constant, we may be able to
2789 reduce the number of bits that we have to clear so that
2790 the mask becomes simple. */
2791 /* ??? This code does not check to see if the new mask is actually
2792 simpler. It may not be. */
2793 rtx op1 = gen_reg_rtx (SImode);
2794 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2795 start of this pattern. */
2796 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2797 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2798
2799 emit_insn (gen_andsi3 (op1, operands[0],
2800 gen_int_mode (~mask2, SImode)));
2801 emit_insn (gen_iorsi3 (subtarget, op1,
2802 gen_int_mode (op3_value << start_bit, SImode)));
2803 }
2804 else if (start_bit == 0
2805 && !(const_ok_for_arm (mask)
2806 || const_ok_for_arm (~mask)))
2807 {
2808 /* A Trick, since we are setting the bottom bits in the word,
2809 we can shift operand[3] up, operand[0] down, OR them together
2810 and rotate the result back again. This takes 3 insns, and
2811 the third might be mergeable into another op. */
2812 /* The shift up copes with the possibility that operand[3] is
2813 wider than the bitfield. */
2814 rtx op0 = gen_reg_rtx (SImode);
2815 rtx op1 = gen_reg_rtx (SImode);
2816
2817 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2818 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2819 emit_insn (gen_iorsi3 (op1, op1, op0));
2820 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2821 }
2822 else if ((width + start_bit == 32)
2823 && !(const_ok_for_arm (mask)
2824 || const_ok_for_arm (~mask)))
2825 {
2826 /* Similar trick, but slightly less efficient. */
2827
2828 rtx op0 = gen_reg_rtx (SImode);
2829 rtx op1 = gen_reg_rtx (SImode);
2830
2831 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2832 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2833 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2834 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2835 }
2836 else
2837 {
2838 rtx op0 = gen_int_mode (mask, SImode);
2839 rtx op1 = gen_reg_rtx (SImode);
2840 rtx op2 = gen_reg_rtx (SImode);
2841
2842 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2843 {
2844 rtx tmp = gen_reg_rtx (SImode);
2845
2846 emit_insn (gen_movsi (tmp, op0));
2847 op0 = tmp;
2848 }
2849
2850 /* Mask out any bits in operand[3] that are not needed. */
2851 emit_insn (gen_andsi3 (op1, operands[3], op0));
2852
2853 if (CONST_INT_P (op0)
2854 && (const_ok_for_arm (mask << start_bit)
2855 || const_ok_for_arm (~(mask << start_bit))))
2856 {
2857 op0 = gen_int_mode (~(mask << start_bit), SImode);
2858 emit_insn (gen_andsi3 (op2, operands[0], op0));
2859 }
2860 else
2861 {
2862 if (CONST_INT_P (op0))
2863 {
2864 rtx tmp = gen_reg_rtx (SImode);
2865
2866 emit_insn (gen_movsi (tmp, op0));
2867 op0 = tmp;
2868 }
2869
2870 if (start_bit != 0)
2871 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2872
2873 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2874 }
2875
2876 if (start_bit != 0)
2877 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2878
2879 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2880 }
2881
2882 if (subtarget != target)
2883 {
2884 /* If TARGET is still a SUBREG, then it must be wider than a word,
2885 so we must be careful only to set the subword we were asked to. */
2886 if (GET_CODE (target) == SUBREG)
2887 emit_move_insn (target, subtarget);
2888 else
2889 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2890 }
2891
2892 DONE;
2893 }"
2894 )
2895
2896 (define_insn "insv_zero"
2897 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2898 (match_operand:SI 1 "const_int_M_operand" "M")
2899 (match_operand:SI 2 "const_int_M_operand" "M"))
2900 (const_int 0))]
2901 "arm_arch_thumb2"
2902 "bfc%?\t%0, %2, %1"
2903 [(set_attr "length" "4")
2904 (set_attr "predicable" "yes")
2905 (set_attr "predicable_short_it" "no")
2906 (set_attr "type" "bfm")]
2907 )
2908
2909 (define_insn "insv_t2"
2910 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2911 (match_operand:SI 1 "const_int_M_operand" "M")
2912 (match_operand:SI 2 "const_int_M_operand" "M"))
2913 (match_operand:SI 3 "s_register_operand" "r"))]
2914 "arm_arch_thumb2"
2915 "bfi%?\t%0, %3, %2, %1"
2916 [(set_attr "length" "4")
2917 (set_attr "predicable" "yes")
2918 (set_attr "predicable_short_it" "no")
2919 (set_attr "type" "bfm")]
2920 )
2921
2922 ; constants for op 2 will never be given to these patterns.
2923 (define_insn_and_split "*anddi_notdi_di"
2924 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2925 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2926 (match_operand:DI 2 "s_register_operand" "r,0")))]
2927 "TARGET_32BIT"
2928 "#"
2929 "TARGET_32BIT && reload_completed
2930 && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2931 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2932 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2933 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2934 "
2935 {
2936 operands[3] = gen_highpart (SImode, operands[0]);
2937 operands[0] = gen_lowpart (SImode, operands[0]);
2938 operands[4] = gen_highpart (SImode, operands[1]);
2939 operands[1] = gen_lowpart (SImode, operands[1]);
2940 operands[5] = gen_highpart (SImode, operands[2]);
2941 operands[2] = gen_lowpart (SImode, operands[2]);
2942 }"
2943 [(set_attr "length" "8")
2944 (set_attr "predicable" "yes")
2945 (set_attr "type" "multiple")]
2946 )
2947
2948 (define_insn_and_split "*anddi_notzesidi_di"
2949 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2950 (and:DI (not:DI (zero_extend:DI
2951 (match_operand:SI 2 "s_register_operand" "r,r")))
2952 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2953 "TARGET_32BIT"
2954 "@
2955 bic%?\\t%Q0, %Q1, %2
2956 #"
2957 ; (not (zero_extend ...)) allows us to just copy the high word from
2958 ; operand1 to operand0.
2959 "TARGET_32BIT
2960 && reload_completed
2961 && operands[0] != operands[1]"
2962 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2963 (set (match_dup 3) (match_dup 4))]
2964 "
2965 {
2966 operands[3] = gen_highpart (SImode, operands[0]);
2967 operands[0] = gen_lowpart (SImode, operands[0]);
2968 operands[4] = gen_highpart (SImode, operands[1]);
2969 operands[1] = gen_lowpart (SImode, operands[1]);
2970 }"
2971 [(set_attr "length" "4,8")
2972 (set_attr "predicable" "yes")
2973 (set_attr "predicable_short_it" "no")
2974 (set_attr "type" "multiple")]
2975 )
2976
2977 (define_insn_and_split "*anddi_notdi_zesidi"
2978 [(set (match_operand:DI 0 "s_register_operand" "=r")
2979 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2980 (zero_extend:DI
2981 (match_operand:SI 1 "s_register_operand" "r"))))]
2982 "TARGET_32BIT"
2983 "#"
2984 "TARGET_32BIT && reload_completed"
2985 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2986 (set (match_dup 3) (const_int 0))]
2987 "
2988 {
2989 operands[3] = gen_highpart (SImode, operands[0]);
2990 operands[0] = gen_lowpart (SImode, operands[0]);
2991 operands[2] = gen_lowpart (SImode, operands[2]);
2992 }"
2993 [(set_attr "length" "8")
2994 (set_attr "predicable" "yes")
2995 (set_attr "predicable_short_it" "no")
2996 (set_attr "type" "multiple")]
2997 )
2998
2999 (define_insn_and_split "*anddi_notsesidi_di"
3000 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3001 (and:DI (not:DI (sign_extend:DI
3002 (match_operand:SI 2 "s_register_operand" "r,r")))
3003 (match_operand:DI 1 "s_register_operand" "0,r")))]
3004 "TARGET_32BIT"
3005 "#"
3006 "TARGET_32BIT && reload_completed"
3007 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
3008 (set (match_dup 3) (and:SI (not:SI
3009 (ashiftrt:SI (match_dup 2) (const_int 31)))
3010 (match_dup 4)))]
3011 "
3012 {
3013 operands[3] = gen_highpart (SImode, operands[0]);
3014 operands[0] = gen_lowpart (SImode, operands[0]);
3015 operands[4] = gen_highpart (SImode, operands[1]);
3016 operands[1] = gen_lowpart (SImode, operands[1]);
3017 }"
3018 [(set_attr "length" "8")
3019 (set_attr "predicable" "yes")
3020 (set_attr "predicable_short_it" "no")
3021 (set_attr "type" "multiple")]
3022 )
3023
3024 (define_insn "andsi_notsi_si"
3025 [(set (match_operand:SI 0 "s_register_operand" "=r")
3026 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3027 (match_operand:SI 1 "s_register_operand" "r")))]
3028 "TARGET_32BIT"
3029 "bic%?\\t%0, %1, %2"
3030 [(set_attr "predicable" "yes")
3031 (set_attr "predicable_short_it" "no")
3032 (set_attr "type" "logic_reg")]
3033 )
3034
3035 (define_insn "andsi_not_shiftsi_si"
3036 [(set (match_operand:SI 0 "s_register_operand" "=r")
3037 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
3038 [(match_operand:SI 2 "s_register_operand" "r")
3039 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
3040 (match_operand:SI 1 "s_register_operand" "r")))]
3041 "TARGET_ARM"
3042 "bic%?\\t%0, %1, %2%S4"
3043 [(set_attr "predicable" "yes")
3044 (set_attr "shift" "2")
3045 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
3046 (const_string "logic_shift_imm")
3047 (const_string "logic_shift_reg")))]
3048 )
3049
3050 ;; Shifted bics pattern used to set up CC status register and not reusing
3051 ;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
3052 ;; does not support shift by register.
3053 (define_insn "andsi_not_shiftsi_si_scc_no_reuse"
3054 [(set (reg:CC_NOOV CC_REGNUM)
3055 (compare:CC_NOOV
3056 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3057 [(match_operand:SI 1 "s_register_operand" "r")
3058 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3059 (match_operand:SI 3 "s_register_operand" "r"))
3060 (const_int 0)))
3061 (clobber (match_scratch:SI 4 "=r"))]
3062 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3063 "bics%?\\t%4, %3, %1%S0"
3064 [(set_attr "predicable" "yes")
3065 (set_attr "predicable_short_it" "no")
3066 (set_attr "conds" "set")
3067 (set_attr "shift" "1")
3068 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3069 (const_string "logic_shift_imm")
3070 (const_string "logic_shift_reg")))]
3071 )
3072
3073 ;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
3074 ;; getting reused later.
3075 (define_insn "andsi_not_shiftsi_si_scc"
3076 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
3077 (compare:CC_NOOV
3078 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
3079 [(match_operand:SI 1 "s_register_operand" "r")
3080 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
3081 (match_operand:SI 3 "s_register_operand" "r"))
3082 (const_int 0)))
3083 (set (match_operand:SI 4 "s_register_operand" "=r")
3084 (and:SI (not:SI (match_op_dup 0
3085 [(match_dup 1)
3086 (match_dup 2)]))
3087 (match_dup 3)))])]
3088 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
3089 "bics%?\\t%4, %3, %1%S0"
3090 [(set_attr "predicable" "yes")
3091 (set_attr "predicable_short_it" "no")
3092 (set_attr "conds" "set")
3093 (set_attr "shift" "1")
3094 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3095 (const_string "logic_shift_imm")
3096 (const_string "logic_shift_reg")))]
3097 )
3098
3099 (define_insn "*andsi_notsi_si_compare0"
3100 [(set (reg:CC_NOOV CC_REGNUM)
3101 (compare:CC_NOOV
3102 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3103 (match_operand:SI 1 "s_register_operand" "r"))
3104 (const_int 0)))
3105 (set (match_operand:SI 0 "s_register_operand" "=r")
3106 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
3107 "TARGET_32BIT"
3108 "bics\\t%0, %1, %2"
3109 [(set_attr "conds" "set")
3110 (set_attr "type" "logics_shift_reg")]
3111 )
3112
3113 (define_insn "*andsi_notsi_si_compare0_scratch"
3114 [(set (reg:CC_NOOV CC_REGNUM)
3115 (compare:CC_NOOV
3116 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
3117 (match_operand:SI 1 "s_register_operand" "r"))
3118 (const_int 0)))
3119 (clobber (match_scratch:SI 0 "=r"))]
3120 "TARGET_32BIT"
3121 "bics\\t%0, %1, %2"
3122 [(set_attr "conds" "set")
3123 (set_attr "type" "logics_shift_reg")]
3124 )
3125
3126 (define_expand "iordi3"
3127 [(set (match_operand:DI 0 "s_register_operand" "")
3128 (ior:DI (match_operand:DI 1 "s_register_operand" "")
3129 (match_operand:DI 2 "neon_logic_op2" "")))]
3130 "TARGET_32BIT"
3131 ""
3132 )
3133
3134 (define_insn_and_split "*iordi3_insn"
3135 [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
3136 (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
3137 (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
3138 "TARGET_32BIT && !TARGET_IWMMXT"
3139 {
3140 switch (which_alternative)
3141 {
3142 case 0: /* fall through */
3143 case 6: return "vorr\t%P0, %P1, %P2";
3144 case 1: /* fall through */
3145 case 7: return neon_output_logic_immediate ("vorr", &operands[2],
3146 DImode, 0, VALID_NEON_QREG_MODE (DImode));
3147 case 2:
3148 case 3:
3149 case 4:
3150 case 5:
3151 return "#";
3152 default: gcc_unreachable ();
3153 }
3154 }
3155 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3156 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3157 [(set (match_dup 3) (match_dup 4))
3158 (set (match_dup 5) (match_dup 6))]
3159 "
3160 {
3161 operands[3] = gen_lowpart (SImode, operands[0]);
3162 operands[5] = gen_highpart (SImode, operands[0]);
3163
3164 operands[4] = simplify_gen_binary (IOR, SImode,
3165 gen_lowpart (SImode, operands[1]),
3166 gen_lowpart (SImode, operands[2]));
3167 operands[6] = simplify_gen_binary (IOR, SImode,
3168 gen_highpart (SImode, operands[1]),
3169 gen_highpart_mode (SImode, DImode, operands[2]));
3170
3171 }"
3172 [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
3173 multiple,neon_logic,neon_logic")
3174 (set_attr "length" "*,*,8,8,8,8,*,*")
3175 (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
3176 )
3177
3178 (define_insn "*iordi_zesidi_di"
3179 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3180 (ior:DI (zero_extend:DI
3181 (match_operand:SI 2 "s_register_operand" "r,r"))
3182 (match_operand:DI 1 "s_register_operand" "0,?r")))]
3183 "TARGET_32BIT"
3184 "@
3185 orr%?\\t%Q0, %Q1, %2
3186 #"
3187 [(set_attr "length" "4,8")
3188 (set_attr "predicable" "yes")
3189 (set_attr "predicable_short_it" "no")
3190 (set_attr "type" "logic_reg,multiple")]
3191 )
3192
3193 (define_insn "*iordi_sesidi_di"
3194 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3195 (ior:DI (sign_extend:DI
3196 (match_operand:SI 2 "s_register_operand" "r,r"))
3197 (match_operand:DI 1 "s_register_operand" "0,r")))]
3198 "TARGET_32BIT"
3199 "#"
3200 [(set_attr "length" "8")
3201 (set_attr "predicable" "yes")
3202 (set_attr "type" "multiple")]
3203 )
3204
3205 (define_expand "iorsi3"
3206 [(set (match_operand:SI 0 "s_register_operand" "")
3207 (ior:SI (match_operand:SI 1 "s_register_operand" "")
3208 (match_operand:SI 2 "reg_or_int_operand" "")))]
3209 "TARGET_EITHER"
3210 "
3211 if (CONST_INT_P (operands[2]))
3212 {
3213 if (TARGET_32BIT)
3214 {
3215 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
3216 operands[2] = force_reg (SImode, operands[2]);
3217 else
3218 {
3219 arm_split_constant (IOR, SImode, NULL_RTX,
3220 INTVAL (operands[2]), operands[0],
3221 operands[1],
3222 optimize && can_create_pseudo_p ());
3223 DONE;
3224 }
3225 }
3226 else /* TARGET_THUMB1 */
3227 {
3228 rtx tmp = force_reg (SImode, operands[2]);
3229 if (rtx_equal_p (operands[0], operands[1]))
3230 operands[2] = tmp;
3231 else
3232 {
3233 operands[2] = operands[1];
3234 operands[1] = tmp;
3235 }
3236 }
3237 }
3238 "
3239 )
3240
3241 (define_insn_and_split "*iorsi3_insn"
3242 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
3243 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
3244 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
3245 "TARGET_32BIT"
3246 "@
3247 orr%?\\t%0, %1, %2
3248 orr%?\\t%0, %1, %2
3249 orn%?\\t%0, %1, #%B2
3250 orr%?\\t%0, %1, %2
3251 #"
3252 "TARGET_32BIT
3253 && CONST_INT_P (operands[2])
3254 && !(const_ok_for_arm (INTVAL (operands[2]))
3255 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
3256 [(clobber (const_int 0))]
3257 {
3258 arm_split_constant (IOR, SImode, curr_insn,
3259 INTVAL (operands[2]), operands[0], operands[1], 0);
3260 DONE;
3261 }
3262 [(set_attr "length" "4,4,4,4,16")
3263 (set_attr "arch" "32,t2,t2,32,32")
3264 (set_attr "predicable" "yes")
3265 (set_attr "predicable_short_it" "no,yes,no,no,no")
3266 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
3267 )
3268
3269 (define_peephole2
3270 [(match_scratch:SI 3 "r")
3271 (set (match_operand:SI 0 "arm_general_register_operand" "")
3272 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
3273 (match_operand:SI 2 "const_int_operand" "")))]
3274 "TARGET_ARM
3275 && !const_ok_for_arm (INTVAL (operands[2]))
3276 && const_ok_for_arm (~INTVAL (operands[2]))"
3277 [(set (match_dup 3) (match_dup 2))
3278 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3279 ""
3280 )
3281
3282 (define_insn "*iorsi3_compare0"
3283 [(set (reg:CC_NOOV CC_REGNUM)
3284 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3285 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
3286 (const_int 0)))
3287 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3288 (ior:SI (match_dup 1) (match_dup 2)))]
3289 "TARGET_32BIT"
3290 "orrs%?\\t%0, %1, %2"
3291 [(set_attr "conds" "set")
3292 (set_attr "type" "logics_imm,logics_reg")]
3293 )
3294
3295 (define_insn "*iorsi3_compare0_scratch"
3296 [(set (reg:CC_NOOV CC_REGNUM)
3297 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3298 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
3299 (const_int 0)))
3300 (clobber (match_scratch:SI 0 "=r,r"))]
3301 "TARGET_32BIT"
3302 "orrs%?\\t%0, %1, %2"
3303 [(set_attr "conds" "set")
3304 (set_attr "type" "logics_imm,logics_reg")]
3305 )
3306
3307 (define_expand "xordi3"
3308 [(set (match_operand:DI 0 "s_register_operand" "")
3309 (xor:DI (match_operand:DI 1 "s_register_operand" "")
3310 (match_operand:DI 2 "arm_xordi_operand" "")))]
3311 "TARGET_32BIT"
3312 {
3313 /* The iWMMXt pattern for xordi3 accepts only register operands but we want
3314 to reuse this expander for all TARGET_32BIT targets so just force the
3315 constants into a register. Unlike for the anddi3 and iordi3 there are
3316 no NEON instructions that take an immediate. */
3317 if (TARGET_IWMMXT && !REG_P (operands[2]))
3318 operands[2] = force_reg (DImode, operands[2]);
3319 }
3320 )
3321
3322 (define_insn_and_split "*xordi3_insn"
3323 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
3324 (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
3325 (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3326 "TARGET_32BIT && !TARGET_IWMMXT"
3327 {
3328 switch (which_alternative)
3329 {
3330 case 1:
3331 case 2:
3332 case 3:
3333 case 4: /* fall through */
3334 return "#";
3335 case 0: /* fall through */
3336 case 5: return "veor\t%P0, %P1, %P2";
3337 default: gcc_unreachable ();
3338 }
3339 }
3340 "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3341 && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3342 [(set (match_dup 3) (match_dup 4))
3343 (set (match_dup 5) (match_dup 6))]
3344 "
3345 {
3346 operands[3] = gen_lowpart (SImode, operands[0]);
3347 operands[5] = gen_highpart (SImode, operands[0]);
3348
3349 operands[4] = simplify_gen_binary (XOR, SImode,
3350 gen_lowpart (SImode, operands[1]),
3351 gen_lowpart (SImode, operands[2]));
3352 operands[6] = simplify_gen_binary (XOR, SImode,
3353 gen_highpart (SImode, operands[1]),
3354 gen_highpart_mode (SImode, DImode, operands[2]));
3355
3356 }"
3357 [(set_attr "length" "*,8,8,8,8,*")
3358 (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
3359 (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
3360 )
3361
3362 (define_insn "*xordi_zesidi_di"
3363 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3364 (xor:DI (zero_extend:DI
3365 (match_operand:SI 2 "s_register_operand" "r,r"))
3366 (match_operand:DI 1 "s_register_operand" "0,?r")))]
3367 "TARGET_32BIT"
3368 "@
3369 eor%?\\t%Q0, %Q1, %2
3370 #"
3371 [(set_attr "length" "4,8")
3372 (set_attr "predicable" "yes")
3373 (set_attr "predicable_short_it" "no")
3374 (set_attr "type" "logic_reg")]
3375 )
3376
3377 (define_insn "*xordi_sesidi_di"
3378 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3379 (xor:DI (sign_extend:DI
3380 (match_operand:SI 2 "s_register_operand" "r,r"))
3381 (match_operand:DI 1 "s_register_operand" "0,r")))]
3382 "TARGET_32BIT"
3383 "#"
3384 [(set_attr "length" "8")
3385 (set_attr "predicable" "yes")
3386 (set_attr "type" "multiple")]
3387 )
3388
3389 (define_expand "xorsi3"
3390 [(set (match_operand:SI 0 "s_register_operand" "")
3391 (xor:SI (match_operand:SI 1 "s_register_operand" "")
3392 (match_operand:SI 2 "reg_or_int_operand" "")))]
3393 "TARGET_EITHER"
3394 "if (CONST_INT_P (operands[2]))
3395 {
3396 if (TARGET_32BIT)
3397 {
3398 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3399 operands[2] = force_reg (SImode, operands[2]);
3400 else
3401 {
3402 arm_split_constant (XOR, SImode, NULL_RTX,
3403 INTVAL (operands[2]), operands[0],
3404 operands[1],
3405 optimize && can_create_pseudo_p ());
3406 DONE;
3407 }
3408 }
3409 else /* TARGET_THUMB1 */
3410 {
3411 rtx tmp = force_reg (SImode, operands[2]);
3412 if (rtx_equal_p (operands[0], operands[1]))
3413 operands[2] = tmp;
3414 else
3415 {
3416 operands[2] = operands[1];
3417 operands[1] = tmp;
3418 }
3419 }
3420 }"
3421 )
3422
3423 (define_insn_and_split "*arm_xorsi3"
3424 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3425 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3426 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
3427 "TARGET_32BIT"
3428 "@
3429 eor%?\\t%0, %1, %2
3430 eor%?\\t%0, %1, %2
3431 eor%?\\t%0, %1, %2
3432 #"
3433 "TARGET_32BIT
3434 && CONST_INT_P (operands[2])
3435 && !const_ok_for_arm (INTVAL (operands[2]))"
3436 [(clobber (const_int 0))]
3437 {
3438 arm_split_constant (XOR, SImode, curr_insn,
3439 INTVAL (operands[2]), operands[0], operands[1], 0);
3440 DONE;
3441 }
3442 [(set_attr "length" "4,4,4,16")
3443 (set_attr "predicable" "yes")
3444 (set_attr "predicable_short_it" "no,yes,no,no")
3445 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
3446 )
3447
3448 (define_insn "*xorsi3_compare0"
3449 [(set (reg:CC_NOOV CC_REGNUM)
3450 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3451 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
3452 (const_int 0)))
3453 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3454 (xor:SI (match_dup 1) (match_dup 2)))]
3455 "TARGET_32BIT"
3456 "eors%?\\t%0, %1, %2"
3457 [(set_attr "conds" "set")
3458 (set_attr "type" "logics_imm,logics_reg")]
3459 )
3460
3461 (define_insn "*xorsi3_compare0_scratch"
3462 [(set (reg:CC_NOOV CC_REGNUM)
3463 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3464 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
3465 (const_int 0)))]
3466 "TARGET_32BIT"
3467 "teq%?\\t%0, %1"
3468 [(set_attr "conds" "set")
3469 (set_attr "type" "logics_imm,logics_reg")]
3470 )
3471
3472 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3473 ; (NOT D) we can sometimes merge the final NOT into one of the following
3474 ; insns.
3475
3476 (define_split
3477 [(set (match_operand:SI 0 "s_register_operand" "")
3478 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3479 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3480 (match_operand:SI 3 "arm_rhs_operand" "")))
3481 (clobber (match_operand:SI 4 "s_register_operand" ""))]
3482 "TARGET_32BIT"
3483 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3484 (not:SI (match_dup 3))))
3485 (set (match_dup 0) (not:SI (match_dup 4)))]
3486 ""
3487 )
3488
3489 (define_insn_and_split "*andsi_iorsi3_notsi"
3490 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3491 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3492 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3493 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3494 "TARGET_32BIT"
3495 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3496 "&& reload_completed"
3497 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3498 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3499 {
3500 /* If operands[3] is a constant make sure to fold the NOT into it
3501 to avoid creating a NOT of a CONST_INT. */
3502 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3503 if (CONST_INT_P (not_rtx))
3504 {
3505 operands[4] = operands[0];
3506 operands[5] = not_rtx;
3507 }
3508 else
3509 {
3510 operands[5] = operands[0];
3511 operands[4] = not_rtx;
3512 }
3513 }
3514 [(set_attr "length" "8")
3515 (set_attr "ce_count" "2")
3516 (set_attr "predicable" "yes")
3517 (set_attr "predicable_short_it" "no")
3518 (set_attr "type" "multiple")]
3519 )
3520
3521 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3522 ; insns are available?
3523 (define_split
3524 [(set (match_operand:SI 0 "s_register_operand" "")
3525 (match_operator:SI 1 "logical_binary_operator"
3526 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3527 (match_operand:SI 3 "const_int_operand" "")
3528 (match_operand:SI 4 "const_int_operand" ""))
3529 (match_operator:SI 9 "logical_binary_operator"
3530 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3531 (match_operand:SI 6 "const_int_operand" ""))
3532 (match_operand:SI 7 "s_register_operand" "")])]))
3533 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3534 "TARGET_32BIT
3535 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3536 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3537 [(set (match_dup 8)
3538 (match_op_dup 1
3539 [(ashift:SI (match_dup 2) (match_dup 4))
3540 (match_dup 5)]))
3541 (set (match_dup 0)
3542 (match_op_dup 1
3543 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3544 (match_dup 7)]))]
3545 "
3546 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3547 ")
3548
3549 (define_split
3550 [(set (match_operand:SI 0 "s_register_operand" "")
3551 (match_operator:SI 1 "logical_binary_operator"
3552 [(match_operator:SI 9 "logical_binary_operator"
3553 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3554 (match_operand:SI 6 "const_int_operand" ""))
3555 (match_operand:SI 7 "s_register_operand" "")])
3556 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3557 (match_operand:SI 3 "const_int_operand" "")
3558 (match_operand:SI 4 "const_int_operand" ""))]))
3559 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3560 "TARGET_32BIT
3561 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3562 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3563 [(set (match_dup 8)
3564 (match_op_dup 1
3565 [(ashift:SI (match_dup 2) (match_dup 4))
3566 (match_dup 5)]))
3567 (set (match_dup 0)
3568 (match_op_dup 1
3569 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3570 (match_dup 7)]))]
3571 "
3572 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3573 ")
3574
3575 (define_split
3576 [(set (match_operand:SI 0 "s_register_operand" "")
3577 (match_operator:SI 1 "logical_binary_operator"
3578 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3579 (match_operand:SI 3 "const_int_operand" "")
3580 (match_operand:SI 4 "const_int_operand" ""))
3581 (match_operator:SI 9 "logical_binary_operator"
3582 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3583 (match_operand:SI 6 "const_int_operand" ""))
3584 (match_operand:SI 7 "s_register_operand" "")])]))
3585 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3586 "TARGET_32BIT
3587 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3588 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3589 [(set (match_dup 8)
3590 (match_op_dup 1
3591 [(ashift:SI (match_dup 2) (match_dup 4))
3592 (match_dup 5)]))
3593 (set (match_dup 0)
3594 (match_op_dup 1
3595 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3596 (match_dup 7)]))]
3597 "
3598 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3599 ")
3600
3601 (define_split
3602 [(set (match_operand:SI 0 "s_register_operand" "")
3603 (match_operator:SI 1 "logical_binary_operator"
3604 [(match_operator:SI 9 "logical_binary_operator"
3605 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3606 (match_operand:SI 6 "const_int_operand" ""))
3607 (match_operand:SI 7 "s_register_operand" "")])
3608 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3609 (match_operand:SI 3 "const_int_operand" "")
3610 (match_operand:SI 4 "const_int_operand" ""))]))
3611 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3612 "TARGET_32BIT
3613 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3614 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3615 [(set (match_dup 8)
3616 (match_op_dup 1
3617 [(ashift:SI (match_dup 2) (match_dup 4))
3618 (match_dup 5)]))
3619 (set (match_dup 0)
3620 (match_op_dup 1
3621 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3622 (match_dup 7)]))]
3623 "
3624 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3625 ")
3626 \f
3627
3628 ;; Minimum and maximum insns
3629
3630 (define_expand "smaxsi3"
3631 [(parallel [
3632 (set (match_operand:SI 0 "s_register_operand" "")
3633 (smax:SI (match_operand:SI 1 "s_register_operand" "")
3634 (match_operand:SI 2 "arm_rhs_operand" "")))
3635 (clobber (reg:CC CC_REGNUM))])]
3636 "TARGET_32BIT"
3637 "
3638 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3639 {
3640 /* No need for a clobber of the condition code register here. */
3641 emit_insn (gen_rtx_SET (operands[0],
3642 gen_rtx_SMAX (SImode, operands[1],
3643 operands[2])));
3644 DONE;
3645 }
3646 ")
3647
3648 (define_insn "*smax_0"
3649 [(set (match_operand:SI 0 "s_register_operand" "=r")
3650 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3651 (const_int 0)))]
3652 "TARGET_32BIT"
3653 "bic%?\\t%0, %1, %1, asr #31"
3654 [(set_attr "predicable" "yes")
3655 (set_attr "predicable_short_it" "no")
3656 (set_attr "type" "logic_shift_reg")]
3657 )
3658
3659 (define_insn "*smax_m1"
3660 [(set (match_operand:SI 0 "s_register_operand" "=r")
3661 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3662 (const_int -1)))]
3663 "TARGET_32BIT"
3664 "orr%?\\t%0, %1, %1, asr #31"
3665 [(set_attr "predicable" "yes")
3666 (set_attr "predicable_short_it" "no")
3667 (set_attr "type" "logic_shift_reg")]
3668 )
3669
3670 (define_insn_and_split "*arm_smax_insn"
3671 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3672 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3673 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3674 (clobber (reg:CC CC_REGNUM))]
3675 "TARGET_ARM"
3676 "#"
3677 ; cmp\\t%1, %2\;movlt\\t%0, %2
3678 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3679 "TARGET_ARM"
3680 [(set (reg:CC CC_REGNUM)
3681 (compare:CC (match_dup 1) (match_dup 2)))
3682 (set (match_dup 0)
3683 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3684 (match_dup 1)
3685 (match_dup 2)))]
3686 ""
3687 [(set_attr "conds" "clob")
3688 (set_attr "length" "8,12")
3689 (set_attr "type" "multiple")]
3690 )
3691
3692 (define_expand "sminsi3"
3693 [(parallel [
3694 (set (match_operand:SI 0 "s_register_operand" "")
3695 (smin:SI (match_operand:SI 1 "s_register_operand" "")
3696 (match_operand:SI 2 "arm_rhs_operand" "")))
3697 (clobber (reg:CC CC_REGNUM))])]
3698 "TARGET_32BIT"
3699 "
3700 if (operands[2] == const0_rtx)
3701 {
3702 /* No need for a clobber of the condition code register here. */
3703 emit_insn (gen_rtx_SET (operands[0],
3704 gen_rtx_SMIN (SImode, operands[1],
3705 operands[2])));
3706 DONE;
3707 }
3708 ")
3709
3710 (define_insn "*smin_0"
3711 [(set (match_operand:SI 0 "s_register_operand" "=r")
3712 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3713 (const_int 0)))]
3714 "TARGET_32BIT"
3715 "and%?\\t%0, %1, %1, asr #31"
3716 [(set_attr "predicable" "yes")
3717 (set_attr "predicable_short_it" "no")
3718 (set_attr "type" "logic_shift_reg")]
3719 )
3720
3721 (define_insn_and_split "*arm_smin_insn"
3722 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3723 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3724 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3725 (clobber (reg:CC CC_REGNUM))]
3726 "TARGET_ARM"
3727 "#"
3728 ; cmp\\t%1, %2\;movge\\t%0, %2
3729 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3730 "TARGET_ARM"
3731 [(set (reg:CC CC_REGNUM)
3732 (compare:CC (match_dup 1) (match_dup 2)))
3733 (set (match_dup 0)
3734 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3735 (match_dup 1)
3736 (match_dup 2)))]
3737 ""
3738 [(set_attr "conds" "clob")
3739 (set_attr "length" "8,12")
3740 (set_attr "type" "multiple,multiple")]
3741 )
3742
3743 (define_expand "umaxsi3"
3744 [(parallel [
3745 (set (match_operand:SI 0 "s_register_operand" "")
3746 (umax:SI (match_operand:SI 1 "s_register_operand" "")
3747 (match_operand:SI 2 "arm_rhs_operand" "")))
3748 (clobber (reg:CC CC_REGNUM))])]
3749 "TARGET_32BIT"
3750 ""
3751 )
3752
3753 (define_insn_and_split "*arm_umaxsi3"
3754 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3755 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3756 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3757 (clobber (reg:CC CC_REGNUM))]
3758 "TARGET_ARM"
3759 "#"
3760 ; cmp\\t%1, %2\;movcc\\t%0, %2
3761 ; cmp\\t%1, %2\;movcs\\t%0, %1
3762 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3763 "TARGET_ARM"
3764 [(set (reg:CC CC_REGNUM)
3765 (compare:CC (match_dup 1) (match_dup 2)))
3766 (set (match_dup 0)
3767 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3768 (match_dup 1)
3769 (match_dup 2)))]
3770 ""
3771 [(set_attr "conds" "clob")
3772 (set_attr "length" "8,8,12")
3773 (set_attr "type" "store1")]
3774 )
3775
3776 (define_expand "uminsi3"
3777 [(parallel [
3778 (set (match_operand:SI 0 "s_register_operand" "")
3779 (umin:SI (match_operand:SI 1 "s_register_operand" "")
3780 (match_operand:SI 2 "arm_rhs_operand" "")))
3781 (clobber (reg:CC CC_REGNUM))])]
3782 "TARGET_32BIT"
3783 ""
3784 )
3785
3786 (define_insn_and_split "*arm_uminsi3"
3787 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3788 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3789 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3790 (clobber (reg:CC CC_REGNUM))]
3791 "TARGET_ARM"
3792 "#"
3793 ; cmp\\t%1, %2\;movcs\\t%0, %2
3794 ; cmp\\t%1, %2\;movcc\\t%0, %1
3795 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3796 "TARGET_ARM"
3797 [(set (reg:CC CC_REGNUM)
3798 (compare:CC (match_dup 1) (match_dup 2)))
3799 (set (match_dup 0)
3800 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3801 (match_dup 1)
3802 (match_dup 2)))]
3803 ""
3804 [(set_attr "conds" "clob")
3805 (set_attr "length" "8,8,12")
3806 (set_attr "type" "store1")]
3807 )
3808
3809 (define_insn "*store_minmaxsi"
3810 [(set (match_operand:SI 0 "memory_operand" "=m")
3811 (match_operator:SI 3 "minmax_operator"
3812 [(match_operand:SI 1 "s_register_operand" "r")
3813 (match_operand:SI 2 "s_register_operand" "r")]))
3814 (clobber (reg:CC CC_REGNUM))]
3815 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
3816 "*
3817 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3818 operands[1], operands[2]);
3819 output_asm_insn (\"cmp\\t%1, %2\", operands);
3820 if (TARGET_THUMB2)
3821 output_asm_insn (\"ite\t%d3\", operands);
3822 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3823 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3824 return \"\";
3825 "
3826 [(set_attr "conds" "clob")
3827 (set (attr "length")
3828 (if_then_else (eq_attr "is_thumb" "yes")
3829 (const_int 14)
3830 (const_int 12)))
3831 (set_attr "type" "store1")]
3832 )
3833
3834 ; Reject the frame pointer in operand[1], since reloading this after
3835 ; it has been eliminated can cause carnage.
3836 (define_insn "*minmax_arithsi"
3837 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3838 (match_operator:SI 4 "shiftable_operator"
3839 [(match_operator:SI 5 "minmax_operator"
3840 [(match_operand:SI 2 "s_register_operand" "r,r")
3841 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3842 (match_operand:SI 1 "s_register_operand" "0,?r")]))
3843 (clobber (reg:CC CC_REGNUM))]
3844 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
3845 "*
3846 {
3847 enum rtx_code code = GET_CODE (operands[4]);
3848 bool need_else;
3849
3850 if (which_alternative != 0 || operands[3] != const0_rtx
3851 || (code != PLUS && code != IOR && code != XOR))
3852 need_else = true;
3853 else
3854 need_else = false;
3855
3856 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3857 operands[2], operands[3]);
3858 output_asm_insn (\"cmp\\t%2, %3\", operands);
3859 if (TARGET_THUMB2)
3860 {
3861 if (need_else)
3862 output_asm_insn (\"ite\\t%d5\", operands);
3863 else
3864 output_asm_insn (\"it\\t%d5\", operands);
3865 }
3866 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3867 if (need_else)
3868 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3869 return \"\";
3870 }"
3871 [(set_attr "conds" "clob")
3872 (set (attr "length")
3873 (if_then_else (eq_attr "is_thumb" "yes")
3874 (const_int 14)
3875 (const_int 12)))
3876 (set_attr "type" "multiple")]
3877 )
3878
3879 ; Reject the frame pointer in operand[1], since reloading this after
3880 ; it has been eliminated can cause carnage.
3881 (define_insn_and_split "*minmax_arithsi_non_canon"
3882 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3883 (minus:SI
3884 (match_operand:SI 1 "s_register_operand" "0,?Ts")
3885 (match_operator:SI 4 "minmax_operator"
3886 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3887 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
3888 (clobber (reg:CC CC_REGNUM))]
3889 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3890 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
3891 "#"
3892 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3893 [(set (reg:CC CC_REGNUM)
3894 (compare:CC (match_dup 2) (match_dup 3)))
3895
3896 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3897 (set (match_dup 0)
3898 (minus:SI (match_dup 1)
3899 (match_dup 2))))
3900 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3901 (set (match_dup 0)
3902 (match_dup 6)))]
3903 {
3904 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3905 operands[2], operands[3]);
3906 enum rtx_code rc = minmax_code (operands[4]);
3907 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3908 operands[2], operands[3]);
3909
3910 if (mode == CCFPmode || mode == CCFPEmode)
3911 rc = reverse_condition_maybe_unordered (rc);
3912 else
3913 rc = reverse_condition (rc);
3914 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
3915 if (CONST_INT_P (operands[3]))
3916 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3917 else
3918 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
3919 }
3920 [(set_attr "conds" "clob")
3921 (set (attr "length")
3922 (if_then_else (eq_attr "is_thumb" "yes")
3923 (const_int 14)
3924 (const_int 12)))
3925 (set_attr "type" "multiple")]
3926 )
3927
3928 (define_code_iterator SAT [smin smax])
3929 (define_code_iterator SATrev [smin smax])
3930 (define_code_attr SATlo [(smin "1") (smax "2")])
3931 (define_code_attr SAThi [(smin "2") (smax "1")])
3932
3933 (define_insn "*satsi_<SAT:code>"
3934 [(set (match_operand:SI 0 "s_register_operand" "=r")
3935 (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3936 (match_operand:SI 1 "const_int_operand" "i"))
3937 (match_operand:SI 2 "const_int_operand" "i")))]
3938 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3939 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3940 {
3941 int mask;
3942 bool signed_sat;
3943 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3944 &mask, &signed_sat))
3945 gcc_unreachable ();
3946
3947 operands[1] = GEN_INT (mask);
3948 if (signed_sat)
3949 return "ssat%?\t%0, %1, %3";
3950 else
3951 return "usat%?\t%0, %1, %3";
3952 }
3953 [(set_attr "predicable" "yes")
3954 (set_attr "predicable_short_it" "no")
3955 (set_attr "type" "alus_imm")]
3956 )
3957
3958 (define_insn "*satsi_<SAT:code>_shift"
3959 [(set (match_operand:SI 0 "s_register_operand" "=r")
3960 (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3961 [(match_operand:SI 4 "s_register_operand" "r")
3962 (match_operand:SI 5 "const_int_operand" "i")])
3963 (match_operand:SI 1 "const_int_operand" "i"))
3964 (match_operand:SI 2 "const_int_operand" "i")))]
3965 "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3966 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3967 {
3968 int mask;
3969 bool signed_sat;
3970 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3971 &mask, &signed_sat))
3972 gcc_unreachable ();
3973
3974 operands[1] = GEN_INT (mask);
3975 if (signed_sat)
3976 return "ssat%?\t%0, %1, %4%S3";
3977 else
3978 return "usat%?\t%0, %1, %4%S3";
3979 }
3980 [(set_attr "predicable" "yes")
3981 (set_attr "predicable_short_it" "no")
3982 (set_attr "shift" "3")
3983 (set_attr "type" "logic_shift_reg")])
3984 \f
3985 ;; Shift and rotation insns
3986
3987 (define_expand "ashldi3"
3988 [(set (match_operand:DI 0 "s_register_operand" "")
3989 (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3990 (match_operand:SI 2 "general_operand" "")))]
3991 "TARGET_32BIT"
3992 "
3993 if (TARGET_NEON)
3994 {
3995 /* Delay the decision whether to use NEON or core-regs until
3996 register allocation. */
3997 emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3998 DONE;
3999 }
4000 else
4001 {
4002 /* Only the NEON case can handle in-memory shift counts. */
4003 if (!reg_or_int_operand (operands[2], SImode))
4004 operands[2] = force_reg (SImode, operands[2]);
4005 }
4006
4007 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
4008 ; /* No special preparation statements; expand pattern as above. */
4009 else
4010 {
4011 rtx scratch1, scratch2;
4012
4013 if (operands[2] == CONST1_RTX (SImode))
4014 {
4015 emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
4016 DONE;
4017 }
4018
4019 /* Ideally we should use iwmmxt here if we could know that operands[1]
4020 ends up already living in an iwmmxt register. Otherwise it's
4021 cheaper to have the alternate code being generated than moving
4022 values to iwmmxt regs and back. */
4023
4024 /* Expand operation using core-registers.
4025 'FAIL' would achieve the same thing, but this is a bit smarter. */
4026 scratch1 = gen_reg_rtx (SImode);
4027 scratch2 = gen_reg_rtx (SImode);
4028 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
4029 operands[2], scratch1, scratch2);
4030 DONE;
4031 }
4032 "
4033 )
4034
4035 (define_insn "arm_ashldi3_1bit"
4036 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4037 (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
4038 (const_int 1)))
4039 (clobber (reg:CC CC_REGNUM))]
4040 "TARGET_32BIT"
4041 "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
4042 [(set_attr "conds" "clob")
4043 (set_attr "length" "8")
4044 (set_attr "type" "multiple")]
4045 )
4046
4047 (define_expand "ashlsi3"
4048 [(set (match_operand:SI 0 "s_register_operand" "")
4049 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
4050 (match_operand:SI 2 "arm_rhs_operand" "")))]
4051 "TARGET_EITHER"
4052 "
4053 if (CONST_INT_P (operands[2])
4054 && (UINTVAL (operands[2])) > 31)
4055 {
4056 emit_insn (gen_movsi (operands[0], const0_rtx));
4057 DONE;
4058 }
4059 "
4060 )
4061
4062 (define_expand "ashrdi3"
4063 [(set (match_operand:DI 0 "s_register_operand" "")
4064 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4065 (match_operand:SI 2 "reg_or_int_operand" "")))]
4066 "TARGET_32BIT"
4067 "
4068 if (TARGET_NEON)
4069 {
4070 /* Delay the decision whether to use NEON or core-regs until
4071 register allocation. */
4072 emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
4073 DONE;
4074 }
4075
4076 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
4077 ; /* No special preparation statements; expand pattern as above. */
4078 else
4079 {
4080 rtx scratch1, scratch2;
4081
4082 if (operands[2] == CONST1_RTX (SImode))
4083 {
4084 emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
4085 DONE;
4086 }
4087
4088 /* Ideally we should use iwmmxt here if we could know that operands[1]
4089 ends up already living in an iwmmxt register. Otherwise it's
4090 cheaper to have the alternate code being generated than moving
4091 values to iwmmxt regs and back. */
4092
4093 /* Expand operation using core-registers.
4094 'FAIL' would achieve the same thing, but this is a bit smarter. */
4095 scratch1 = gen_reg_rtx (SImode);
4096 scratch2 = gen_reg_rtx (SImode);
4097 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
4098 operands[2], scratch1, scratch2);
4099 DONE;
4100 }
4101 "
4102 )
4103
4104 (define_insn "arm_ashrdi3_1bit"
4105 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4106 (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
4107 (const_int 1)))
4108 (clobber (reg:CC CC_REGNUM))]
4109 "TARGET_32BIT"
4110 "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
4111 [(set_attr "conds" "clob")
4112 (set_attr "length" "8")
4113 (set_attr "type" "multiple")]
4114 )
4115
4116 (define_expand "ashrsi3"
4117 [(set (match_operand:SI 0 "s_register_operand" "")
4118 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4119 (match_operand:SI 2 "arm_rhs_operand" "")))]
4120 "TARGET_EITHER"
4121 "
4122 if (CONST_INT_P (operands[2])
4123 && UINTVAL (operands[2]) > 31)
4124 operands[2] = GEN_INT (31);
4125 "
4126 )
4127
4128 (define_expand "lshrdi3"
4129 [(set (match_operand:DI 0 "s_register_operand" "")
4130 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
4131 (match_operand:SI 2 "reg_or_int_operand" "")))]
4132 "TARGET_32BIT"
4133 "
4134 if (TARGET_NEON)
4135 {
4136 /* Delay the decision whether to use NEON or core-regs until
4137 register allocation. */
4138 emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
4139 DONE;
4140 }
4141
4142 if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
4143 ; /* No special preparation statements; expand pattern as above. */
4144 else
4145 {
4146 rtx scratch1, scratch2;
4147
4148 if (operands[2] == CONST1_RTX (SImode))
4149 {
4150 emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
4151 DONE;
4152 }
4153
4154 /* Ideally we should use iwmmxt here if we could know that operands[1]
4155 ends up already living in an iwmmxt register. Otherwise it's
4156 cheaper to have the alternate code being generated than moving
4157 values to iwmmxt regs and back. */
4158
4159 /* Expand operation using core-registers.
4160 'FAIL' would achieve the same thing, but this is a bit smarter. */
4161 scratch1 = gen_reg_rtx (SImode);
4162 scratch2 = gen_reg_rtx (SImode);
4163 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
4164 operands[2], scratch1, scratch2);
4165 DONE;
4166 }
4167 "
4168 )
4169
4170 (define_insn "arm_lshrdi3_1bit"
4171 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4172 (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
4173 (const_int 1)))
4174 (clobber (reg:CC CC_REGNUM))]
4175 "TARGET_32BIT"
4176 "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
4177 [(set_attr "conds" "clob")
4178 (set_attr "length" "8")
4179 (set_attr "type" "multiple")]
4180 )
4181
4182 (define_expand "lshrsi3"
4183 [(set (match_operand:SI 0 "s_register_operand" "")
4184 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
4185 (match_operand:SI 2 "arm_rhs_operand" "")))]
4186 "TARGET_EITHER"
4187 "
4188 if (CONST_INT_P (operands[2])
4189 && (UINTVAL (operands[2])) > 31)
4190 {
4191 emit_insn (gen_movsi (operands[0], const0_rtx));
4192 DONE;
4193 }
4194 "
4195 )
4196
4197 (define_expand "rotlsi3"
4198 [(set (match_operand:SI 0 "s_register_operand" "")
4199 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4200 (match_operand:SI 2 "reg_or_int_operand" "")))]
4201 "TARGET_32BIT"
4202 "
4203 if (CONST_INT_P (operands[2]))
4204 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
4205 else
4206 {
4207 rtx reg = gen_reg_rtx (SImode);
4208 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
4209 operands[2] = reg;
4210 }
4211 "
4212 )
4213
4214 (define_expand "rotrsi3"
4215 [(set (match_operand:SI 0 "s_register_operand" "")
4216 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
4217 (match_operand:SI 2 "arm_rhs_operand" "")))]
4218 "TARGET_EITHER"
4219 "
4220 if (TARGET_32BIT)
4221 {
4222 if (CONST_INT_P (operands[2])
4223 && UINTVAL (operands[2]) > 31)
4224 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
4225 }
4226 else /* TARGET_THUMB1 */
4227 {
4228 if (CONST_INT_P (operands [2]))
4229 operands [2] = force_reg (SImode, operands[2]);
4230 }
4231 "
4232 )
4233
4234 (define_insn "*arm_shiftsi3"
4235 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
4236 (match_operator:SI 3 "shift_operator"
4237 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
4238 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
4239 "TARGET_32BIT"
4240 "* return arm_output_shift(operands, 0);"
4241 [(set_attr "predicable" "yes")
4242 (set_attr "arch" "t2,t2,*,*")
4243 (set_attr "predicable_short_it" "yes,yes,no,no")
4244 (set_attr "length" "4")
4245 (set_attr "shift" "1")
4246 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
4247 )
4248
4249 (define_insn "*shiftsi3_compare0"
4250 [(set (reg:CC_NOOV CC_REGNUM)
4251 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
4252 [(match_operand:SI 1 "s_register_operand" "r,r")
4253 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
4254 (const_int 0)))
4255 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4256 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
4257 "TARGET_32BIT"
4258 "* return arm_output_shift(operands, 1);"
4259 [(set_attr "conds" "set")
4260 (set_attr "shift" "1")
4261 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
4262 )
4263
4264 (define_insn "*shiftsi3_compare0_scratch"
4265 [(set (reg:CC_NOOV CC_REGNUM)
4266 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
4267 [(match_operand:SI 1 "s_register_operand" "r,r")
4268 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
4269 (const_int 0)))
4270 (clobber (match_scratch:SI 0 "=r,r"))]
4271 "TARGET_32BIT"
4272 "* return arm_output_shift(operands, 1);"
4273 [(set_attr "conds" "set")
4274 (set_attr "shift" "1")
4275 (set_attr "type" "shift_imm,shift_reg")]
4276 )
4277
4278 (define_insn "*not_shiftsi"
4279 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
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 "TARGET_32BIT"
4284 "mvn%?\\t%0, %1%S3"
4285 [(set_attr "predicable" "yes")
4286 (set_attr "predicable_short_it" "no")
4287 (set_attr "shift" "1")
4288 (set_attr "arch" "32,a")
4289 (set_attr "type" "mvn_shift,mvn_shift_reg")])
4290
4291 (define_insn "*not_shiftsi_compare0"
4292 [(set (reg:CC_NOOV CC_REGNUM)
4293 (compare:CC_NOOV
4294 (not:SI (match_operator:SI 3 "shift_operator"
4295 [(match_operand:SI 1 "s_register_operand" "r,r")
4296 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4297 (const_int 0)))
4298 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4299 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
4300 "TARGET_32BIT"
4301 "mvns%?\\t%0, %1%S3"
4302 [(set_attr "conds" "set")
4303 (set_attr "shift" "1")
4304 (set_attr "arch" "32,a")
4305 (set_attr "type" "mvn_shift,mvn_shift_reg")])
4306
4307 (define_insn "*not_shiftsi_compare0_scratch"
4308 [(set (reg:CC_NOOV CC_REGNUM)
4309 (compare:CC_NOOV
4310 (not:SI (match_operator:SI 3 "shift_operator"
4311 [(match_operand:SI 1 "s_register_operand" "r,r")
4312 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4313 (const_int 0)))
4314 (clobber (match_scratch:SI 0 "=r,r"))]
4315 "TARGET_32BIT"
4316 "mvns%?\\t%0, %1%S3"
4317 [(set_attr "conds" "set")
4318 (set_attr "shift" "1")
4319 (set_attr "arch" "32,a")
4320 (set_attr "type" "mvn_shift,mvn_shift_reg")])
4321
4322 ;; We don't really have extzv, but defining this using shifts helps
4323 ;; to reduce register pressure later on.
4324
4325 (define_expand "extzv"
4326 [(set (match_operand 0 "s_register_operand" "")
4327 (zero_extract (match_operand 1 "nonimmediate_operand" "")
4328 (match_operand 2 "const_int_operand" "")
4329 (match_operand 3 "const_int_operand" "")))]
4330 "TARGET_THUMB1 || arm_arch_thumb2"
4331 "
4332 {
4333 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4334 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4335
4336 if (arm_arch_thumb2)
4337 {
4338 HOST_WIDE_INT width = INTVAL (operands[2]);
4339 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4340
4341 if (unaligned_access && MEM_P (operands[1])
4342 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4343 {
4344 rtx base_addr;
4345
4346 if (BYTES_BIG_ENDIAN)
4347 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4348 - bitpos;
4349
4350 if (width == 32)
4351 {
4352 base_addr = adjust_address (operands[1], SImode,
4353 bitpos / BITS_PER_UNIT);
4354 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4355 }
4356 else
4357 {
4358 rtx dest = operands[0];
4359 rtx tmp = gen_reg_rtx (SImode);
4360
4361 /* We may get a paradoxical subreg here. Strip it off. */
4362 if (GET_CODE (dest) == SUBREG
4363 && GET_MODE (dest) == SImode
4364 && GET_MODE (SUBREG_REG (dest)) == HImode)
4365 dest = SUBREG_REG (dest);
4366
4367 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4368 FAIL;
4369
4370 base_addr = adjust_address (operands[1], HImode,
4371 bitpos / BITS_PER_UNIT);
4372 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4373 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4374 }
4375 DONE;
4376 }
4377 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4378 {
4379 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4380 operands[3]));
4381 DONE;
4382 }
4383 else
4384 FAIL;
4385 }
4386
4387 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4388 FAIL;
4389
4390 operands[3] = GEN_INT (rshift);
4391
4392 if (lshift == 0)
4393 {
4394 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4395 DONE;
4396 }
4397
4398 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4399 operands[3], gen_reg_rtx (SImode)));
4400 DONE;
4401 }"
4402 )
4403
4404 ;; Helper for extzv, for the Thumb-1 register-shifts case.
4405
4406 (define_expand "extzv_t1"
4407 [(set (match_operand:SI 4 "s_register_operand" "")
4408 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4409 (match_operand:SI 2 "const_int_operand" "")))
4410 (set (match_operand:SI 0 "s_register_operand" "")
4411 (lshiftrt:SI (match_dup 4)
4412 (match_operand:SI 3 "const_int_operand" "")))]
4413 "TARGET_THUMB1"
4414 "")
4415
4416 (define_expand "extv"
4417 [(set (match_operand 0 "s_register_operand" "")
4418 (sign_extract (match_operand 1 "nonimmediate_operand" "")
4419 (match_operand 2 "const_int_operand" "")
4420 (match_operand 3 "const_int_operand" "")))]
4421 "arm_arch_thumb2"
4422 {
4423 HOST_WIDE_INT width = INTVAL (operands[2]);
4424 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4425
4426 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4427 && (bitpos % BITS_PER_UNIT) == 0)
4428 {
4429 rtx base_addr;
4430
4431 if (BYTES_BIG_ENDIAN)
4432 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4433
4434 if (width == 32)
4435 {
4436 base_addr = adjust_address (operands[1], SImode,
4437 bitpos / BITS_PER_UNIT);
4438 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4439 }
4440 else
4441 {
4442 rtx dest = operands[0];
4443 rtx tmp = gen_reg_rtx (SImode);
4444
4445 /* We may get a paradoxical subreg here. Strip it off. */
4446 if (GET_CODE (dest) == SUBREG
4447 && GET_MODE (dest) == SImode
4448 && GET_MODE (SUBREG_REG (dest)) == HImode)
4449 dest = SUBREG_REG (dest);
4450
4451 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4452 FAIL;
4453
4454 base_addr = adjust_address (operands[1], HImode,
4455 bitpos / BITS_PER_UNIT);
4456 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4457 emit_move_insn (gen_lowpart (SImode, dest), tmp);
4458 }
4459
4460 DONE;
4461 }
4462 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4463 FAIL;
4464 else if (GET_MODE (operands[0]) == SImode
4465 && GET_MODE (operands[1]) == SImode)
4466 {
4467 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4468 operands[3]));
4469 DONE;
4470 }
4471
4472 FAIL;
4473 })
4474
4475 ; Helper to expand register forms of extv with the proper modes.
4476
4477 (define_expand "extv_regsi"
4478 [(set (match_operand:SI 0 "s_register_operand" "")
4479 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4480 (match_operand 2 "const_int_operand" "")
4481 (match_operand 3 "const_int_operand" "")))]
4482 ""
4483 {
4484 })
4485
4486 ; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4487
4488 (define_insn "unaligned_loadsi"
4489 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4490 (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4491 UNSPEC_UNALIGNED_LOAD))]
4492 "unaligned_access"
4493 "ldr%?\t%0, %1\t@ unaligned"
4494 [(set_attr "arch" "t2,any")
4495 (set_attr "length" "2,4")
4496 (set_attr "predicable" "yes")
4497 (set_attr "predicable_short_it" "yes,no")
4498 (set_attr "type" "load1")])
4499
4500 (define_insn "unaligned_loadhis"
4501 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4502 (sign_extend:SI
4503 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
4504 UNSPEC_UNALIGNED_LOAD)))]
4505 "unaligned_access"
4506 "ldrsh%?\t%0, %1\t@ unaligned"
4507 [(set_attr "arch" "t2,any")
4508 (set_attr "length" "2,4")
4509 (set_attr "predicable" "yes")
4510 (set_attr "predicable_short_it" "yes,no")
4511 (set_attr "type" "load_byte")])
4512
4513 (define_insn "unaligned_loadhiu"
4514 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4515 (zero_extend:SI
4516 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4517 UNSPEC_UNALIGNED_LOAD)))]
4518 "unaligned_access"
4519 "ldrh%?\t%0, %1\t@ unaligned"
4520 [(set_attr "arch" "t2,any")
4521 (set_attr "length" "2,4")
4522 (set_attr "predicable" "yes")
4523 (set_attr "predicable_short_it" "yes,no")
4524 (set_attr "type" "load_byte")])
4525
4526 (define_insn "unaligned_storesi"
4527 [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4528 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4529 UNSPEC_UNALIGNED_STORE))]
4530 "unaligned_access"
4531 "str%?\t%1, %0\t@ unaligned"
4532 [(set_attr "arch" "t2,any")
4533 (set_attr "length" "2,4")
4534 (set_attr "predicable" "yes")
4535 (set_attr "predicable_short_it" "yes,no")
4536 (set_attr "type" "store1")])
4537
4538 (define_insn "unaligned_storehi"
4539 [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4540 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4541 UNSPEC_UNALIGNED_STORE))]
4542 "unaligned_access"
4543 "strh%?\t%1, %0\t@ unaligned"
4544 [(set_attr "arch" "t2,any")
4545 (set_attr "length" "2,4")
4546 (set_attr "predicable" "yes")
4547 (set_attr "predicable_short_it" "yes,no")
4548 (set_attr "type" "store1")])
4549
4550
4551 (define_insn "*extv_reg"
4552 [(set (match_operand:SI 0 "s_register_operand" "=r")
4553 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4554 (match_operand:SI 2 "const_int_operand" "n")
4555 (match_operand:SI 3 "const_int_operand" "n")))]
4556 "arm_arch_thumb2
4557 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4558 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
4559 "sbfx%?\t%0, %1, %3, %2"
4560 [(set_attr "length" "4")
4561 (set_attr "predicable" "yes")
4562 (set_attr "predicable_short_it" "no")
4563 (set_attr "type" "bfm")]
4564 )
4565
4566 (define_insn "extzv_t2"
4567 [(set (match_operand:SI 0 "s_register_operand" "=r")
4568 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4569 (match_operand:SI 2 "const_int_operand" "n")
4570 (match_operand:SI 3 "const_int_operand" "n")))]
4571 "arm_arch_thumb2
4572 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4573 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
4574 "ubfx%?\t%0, %1, %3, %2"
4575 [(set_attr "length" "4")
4576 (set_attr "predicable" "yes")
4577 (set_attr "predicable_short_it" "no")
4578 (set_attr "type" "bfm")]
4579 )
4580
4581
4582 ;; Division instructions
4583 (define_insn "divsi3"
4584 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4585 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4586 (match_operand:SI 2 "s_register_operand" "r,r")))]
4587 "TARGET_IDIV"
4588 "@
4589 sdiv%?\t%0, %1, %2
4590 sdiv\t%0, %1, %2"
4591 [(set_attr "arch" "32,v8mb")
4592 (set_attr "predicable" "yes")
4593 (set_attr "predicable_short_it" "no")
4594 (set_attr "type" "sdiv")]
4595 )
4596
4597 (define_insn "udivsi3"
4598 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4599 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4600 (match_operand:SI 2 "s_register_operand" "r,r")))]
4601 "TARGET_IDIV"
4602 "@
4603 udiv%?\t%0, %1, %2
4604 udiv\t%0, %1, %2"
4605 [(set_attr "arch" "32,v8mb")
4606 (set_attr "predicable" "yes")
4607 (set_attr "predicable_short_it" "no")
4608 (set_attr "type" "udiv")]
4609 )
4610
4611 \f
4612 ;; Unary arithmetic insns
4613
4614 (define_expand "negvsi3"
4615 [(match_operand:SI 0 "register_operand")
4616 (match_operand:SI 1 "register_operand")
4617 (match_operand 2 "")]
4618 "TARGET_32BIT"
4619 {
4620 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4621 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4622
4623 DONE;
4624 })
4625
4626 (define_expand "negvdi3"
4627 [(match_operand:DI 0 "register_operand")
4628 (match_operand:DI 1 "register_operand")
4629 (match_operand 2 "")]
4630 "TARGET_ARM"
4631 {
4632 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4633 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4634
4635 DONE;
4636 })
4637
4638
4639 (define_insn_and_split "negdi2_compare"
4640 [(set (reg:CC CC_REGNUM)
4641 (compare:CC
4642 (const_int 0)
4643 (match_operand:DI 1 "register_operand" "0,r")))
4644 (set (match_operand:DI 0 "register_operand" "=r,&r")
4645 (minus:DI (const_int 0) (match_dup 1)))]
4646 "TARGET_ARM"
4647 "#"
4648 "&& reload_completed"
4649 [(parallel [(set (reg:CC CC_REGNUM)
4650 (compare:CC (const_int 0) (match_dup 1)))
4651 (set (match_dup 0) (minus:SI (const_int 0)
4652 (match_dup 1)))])
4653 (parallel [(set (reg:CC CC_REGNUM)
4654 (compare:CC (const_int 0) (match_dup 3)))
4655 (set (match_dup 2)
4656 (minus:SI
4657 (minus:SI (const_int 0) (match_dup 3))
4658 (ltu:SI (reg:CC_C CC_REGNUM)
4659 (const_int 0))))])]
4660 {
4661 operands[2] = gen_highpart (SImode, operands[0]);
4662 operands[0] = gen_lowpart (SImode, operands[0]);
4663 operands[3] = gen_highpart (SImode, operands[1]);
4664 operands[1] = gen_lowpart (SImode, operands[1]);
4665 }
4666 [(set_attr "conds" "set")
4667 (set_attr "length" "8")
4668 (set_attr "type" "multiple")]
4669 )
4670
4671 (define_expand "negdi2"
4672 [(parallel
4673 [(set (match_operand:DI 0 "s_register_operand" "")
4674 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
4675 (clobber (reg:CC CC_REGNUM))])]
4676 "TARGET_EITHER"
4677 {
4678 if (TARGET_NEON)
4679 {
4680 emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4681 DONE;
4682 }
4683 }
4684 )
4685
4686 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
4687 ;; The first alternative allows the common case of a *full* overlap.
4688 (define_insn_and_split "*negdi2_insn"
4689 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4690 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
4691 (clobber (reg:CC CC_REGNUM))]
4692 "TARGET_32BIT"
4693 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4694 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
4695 "&& reload_completed"
4696 [(parallel [(set (reg:CC CC_REGNUM)
4697 (compare:CC (const_int 0) (match_dup 1)))
4698 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4699 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4700 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4701 {
4702 operands[2] = gen_highpart (SImode, operands[0]);
4703 operands[0] = gen_lowpart (SImode, operands[0]);
4704 operands[3] = gen_highpart (SImode, operands[1]);
4705 operands[1] = gen_lowpart (SImode, operands[1]);
4706 }
4707 [(set_attr "conds" "clob")
4708 (set_attr "length" "8")
4709 (set_attr "type" "multiple")]
4710 )
4711
4712 (define_insn "*negsi2_carryin_compare"
4713 [(set (reg:CC CC_REGNUM)
4714 (compare:CC (const_int 0)
4715 (match_operand:SI 1 "s_register_operand" "r")))
4716 (set (match_operand:SI 0 "s_register_operand" "=r")
4717 (minus:SI (minus:SI (const_int 0)
4718 (match_dup 1))
4719 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4720 "TARGET_ARM"
4721 "rscs\\t%0, %1, #0"
4722 [(set_attr "conds" "set")
4723 (set_attr "type" "alus_imm")]
4724 )
4725
4726 (define_expand "negsi2"
4727 [(set (match_operand:SI 0 "s_register_operand" "")
4728 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4729 "TARGET_EITHER"
4730 ""
4731 )
4732
4733 (define_insn "*arm_negsi2"
4734 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4735 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
4736 "TARGET_32BIT"
4737 "rsb%?\\t%0, %1, #0"
4738 [(set_attr "predicable" "yes")
4739 (set_attr "predicable_short_it" "yes,no")
4740 (set_attr "arch" "t2,*")
4741 (set_attr "length" "4")
4742 (set_attr "type" "alu_sreg")]
4743 )
4744
4745 (define_expand "negsf2"
4746 [(set (match_operand:SF 0 "s_register_operand" "")
4747 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
4748 "TARGET_32BIT && TARGET_HARD_FLOAT"
4749 ""
4750 )
4751
4752 (define_expand "negdf2"
4753 [(set (match_operand:DF 0 "s_register_operand" "")
4754 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
4755 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
4756 "")
4757
4758 (define_insn_and_split "*zextendsidi_negsi"
4759 [(set (match_operand:DI 0 "s_register_operand" "=r")
4760 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4761 "TARGET_32BIT"
4762 "#"
4763 ""
4764 [(set (match_dup 2)
4765 (neg:SI (match_dup 1)))
4766 (set (match_dup 3)
4767 (const_int 0))]
4768 {
4769 operands[2] = gen_lowpart (SImode, operands[0]);
4770 operands[3] = gen_highpart (SImode, operands[0]);
4771 }
4772 [(set_attr "length" "8")
4773 (set_attr "type" "multiple")]
4774 )
4775
4776 ;; Negate an extended 32-bit value.
4777 (define_insn_and_split "*negdi_extendsidi"
4778 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4779 (neg:DI (sign_extend:DI
4780 (match_operand:SI 1 "s_register_operand" "l,r"))))
4781 (clobber (reg:CC CC_REGNUM))]
4782 "TARGET_32BIT"
4783 "#"
4784 "&& reload_completed"
4785 [(const_int 0)]
4786 {
4787 rtx low = gen_lowpart (SImode, operands[0]);
4788 rtx high = gen_highpart (SImode, operands[0]);
4789
4790 if (reg_overlap_mentioned_p (low, operands[1]))
4791 {
4792 /* Input overlaps the low word of the output. Use:
4793 asr Rhi, Rin, #31
4794 rsbs Rlo, Rin, #0
4795 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4796 rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4797
4798 emit_insn (gen_rtx_SET (high,
4799 gen_rtx_ASHIFTRT (SImode, operands[1],
4800 GEN_INT (31))));
4801
4802 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4803 if (TARGET_ARM)
4804 emit_insn (gen_rtx_SET (high,
4805 gen_rtx_MINUS (SImode,
4806 gen_rtx_MINUS (SImode,
4807 const0_rtx,
4808 high),
4809 gen_rtx_LTU (SImode,
4810 cc_reg,
4811 const0_rtx))));
4812 else
4813 {
4814 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4815 emit_insn (gen_rtx_SET (high,
4816 gen_rtx_MINUS (SImode,
4817 gen_rtx_MINUS (SImode,
4818 high,
4819 two_x),
4820 gen_rtx_LTU (SImode,
4821 cc_reg,
4822 const0_rtx))));
4823 }
4824 }
4825 else
4826 {
4827 /* No overlap, or overlap on high word. Use:
4828 rsb Rlo, Rin, #0
4829 bic Rhi, Rlo, Rin
4830 asr Rhi, Rhi, #31
4831 Flags not needed for this sequence. */
4832 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4833 emit_insn (gen_rtx_SET (high,
4834 gen_rtx_AND (SImode,
4835 gen_rtx_NOT (SImode, operands[1]),
4836 low)));
4837 emit_insn (gen_rtx_SET (high,
4838 gen_rtx_ASHIFTRT (SImode, high,
4839 GEN_INT (31))));
4840 }
4841 DONE;
4842 }
4843 [(set_attr "length" "12")
4844 (set_attr "arch" "t2,*")
4845 (set_attr "type" "multiple")]
4846 )
4847
4848 (define_insn_and_split "*negdi_zero_extendsidi"
4849 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4850 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4851 (clobber (reg:CC CC_REGNUM))]
4852 "TARGET_32BIT"
4853 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4854 ;; Don't care what register is input to sbc,
4855 ;; since we just need to propagate the carry.
4856 "&& reload_completed"
4857 [(parallel [(set (reg:CC CC_REGNUM)
4858 (compare:CC (const_int 0) (match_dup 1)))
4859 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4860 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4861 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4862 {
4863 operands[2] = gen_highpart (SImode, operands[0]);
4864 operands[0] = gen_lowpart (SImode, operands[0]);
4865 }
4866 [(set_attr "conds" "clob")
4867 (set_attr "length" "8")
4868 (set_attr "type" "multiple")] ;; length in thumb is 4
4869 )
4870
4871 ;; abssi2 doesn't really clobber the condition codes if a different register
4872 ;; is being set. To keep things simple, assume during rtl manipulations that
4873 ;; it does, but tell the final scan operator the truth. Similarly for
4874 ;; (neg (abs...))
4875
4876 (define_expand "abssi2"
4877 [(parallel
4878 [(set (match_operand:SI 0 "s_register_operand" "")
4879 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
4880 (clobber (match_dup 2))])]
4881 "TARGET_EITHER"
4882 "
4883 if (TARGET_THUMB1)
4884 operands[2] = gen_rtx_SCRATCH (SImode);
4885 else
4886 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4887 ")
4888
4889 (define_insn_and_split "*arm_abssi2"
4890 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4891 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
4892 (clobber (reg:CC CC_REGNUM))]
4893 "TARGET_ARM"
4894 "#"
4895 "&& reload_completed"
4896 [(const_int 0)]
4897 {
4898 /* if (which_alternative == 0) */
4899 if (REGNO(operands[0]) == REGNO(operands[1]))
4900 {
4901 /* Emit the pattern:
4902 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4903 [(set (reg:CC CC_REGNUM)
4904 (compare:CC (match_dup 0) (const_int 0)))
4905 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4906 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4907 */
4908 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4909 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4910 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4911 (gen_rtx_LT (SImode,
4912 gen_rtx_REG (CCmode, CC_REGNUM),
4913 const0_rtx)),
4914 (gen_rtx_SET (operands[0],
4915 (gen_rtx_MINUS (SImode,
4916 const0_rtx,
4917 operands[1]))))));
4918 DONE;
4919 }
4920 else
4921 {
4922 /* Emit the pattern:
4923 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4924 [(set (match_dup 0)
4925 (xor:SI (match_dup 1)
4926 (ashiftrt:SI (match_dup 1) (const_int 31))))
4927 (set (match_dup 0)
4928 (minus:SI (match_dup 0)
4929 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4930 */
4931 emit_insn (gen_rtx_SET (operands[0],
4932 gen_rtx_XOR (SImode,
4933 gen_rtx_ASHIFTRT (SImode,
4934 operands[1],
4935 GEN_INT (31)),
4936 operands[1])));
4937 emit_insn (gen_rtx_SET (operands[0],
4938 gen_rtx_MINUS (SImode,
4939 operands[0],
4940 gen_rtx_ASHIFTRT (SImode,
4941 operands[1],
4942 GEN_INT (31)))));
4943 DONE;
4944 }
4945 }
4946 [(set_attr "conds" "clob,*")
4947 (set_attr "shift" "1")
4948 (set_attr "predicable" "no, yes")
4949 (set_attr "length" "8")
4950 (set_attr "type" "multiple")]
4951 )
4952
4953 (define_insn_and_split "*arm_neg_abssi2"
4954 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4955 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
4956 (clobber (reg:CC CC_REGNUM))]
4957 "TARGET_ARM"
4958 "#"
4959 "&& reload_completed"
4960 [(const_int 0)]
4961 {
4962 /* if (which_alternative == 0) */
4963 if (REGNO (operands[0]) == REGNO (operands[1]))
4964 {
4965 /* Emit the pattern:
4966 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4967 */
4968 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4969 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4970 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4971 gen_rtx_GT (SImode,
4972 gen_rtx_REG (CCmode, CC_REGNUM),
4973 const0_rtx),
4974 gen_rtx_SET (operands[0],
4975 (gen_rtx_MINUS (SImode,
4976 const0_rtx,
4977 operands[1])))));
4978 }
4979 else
4980 {
4981 /* Emit the pattern:
4982 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4983 */
4984 emit_insn (gen_rtx_SET (operands[0],
4985 gen_rtx_XOR (SImode,
4986 gen_rtx_ASHIFTRT (SImode,
4987 operands[1],
4988 GEN_INT (31)),
4989 operands[1])));
4990 emit_insn (gen_rtx_SET (operands[0],
4991 gen_rtx_MINUS (SImode,
4992 gen_rtx_ASHIFTRT (SImode,
4993 operands[1],
4994 GEN_INT (31)),
4995 operands[0])));
4996 }
4997 DONE;
4998 }
4999 [(set_attr "conds" "clob,*")
5000 (set_attr "shift" "1")
5001 (set_attr "predicable" "no, yes")
5002 (set_attr "length" "8")
5003 (set_attr "type" "multiple")]
5004 )
5005
5006 (define_expand "abssf2"
5007 [(set (match_operand:SF 0 "s_register_operand" "")
5008 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
5009 "TARGET_32BIT && TARGET_HARD_FLOAT"
5010 "")
5011
5012 (define_expand "absdf2"
5013 [(set (match_operand:DF 0 "s_register_operand" "")
5014 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
5015 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5016 "")
5017
5018 (define_expand "sqrtsf2"
5019 [(set (match_operand:SF 0 "s_register_operand" "")
5020 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
5021 "TARGET_32BIT && TARGET_HARD_FLOAT"
5022 "")
5023
5024 (define_expand "sqrtdf2"
5025 [(set (match_operand:DF 0 "s_register_operand" "")
5026 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
5027 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
5028 "")
5029
5030 (define_insn_and_split "one_cmpldi2"
5031 [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
5032 (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
5033 "TARGET_32BIT"
5034 "@
5035 vmvn\t%P0, %P1
5036 #
5037 #
5038 vmvn\t%P0, %P1"
5039 "TARGET_32BIT && reload_completed
5040 && arm_general_register_operand (operands[0], DImode)"
5041 [(set (match_dup 0) (not:SI (match_dup 1)))
5042 (set (match_dup 2) (not:SI (match_dup 3)))]
5043 "
5044 {
5045 operands[2] = gen_highpart (SImode, operands[0]);
5046 operands[0] = gen_lowpart (SImode, operands[0]);
5047 operands[3] = gen_highpart (SImode, operands[1]);
5048 operands[1] = gen_lowpart (SImode, operands[1]);
5049 }"
5050 [(set_attr "length" "*,8,8,*")
5051 (set_attr "predicable" "no,yes,yes,no")
5052 (set_attr "type" "neon_move,multiple,multiple,neon_move")
5053 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
5054 )
5055
5056 (define_expand "one_cmplsi2"
5057 [(set (match_operand:SI 0 "s_register_operand" "")
5058 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
5059 "TARGET_EITHER"
5060 ""
5061 )
5062
5063 (define_insn "*arm_one_cmplsi2"
5064 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
5065 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
5066 "TARGET_32BIT"
5067 "mvn%?\\t%0, %1"
5068 [(set_attr "predicable" "yes")
5069 (set_attr "predicable_short_it" "yes,no")
5070 (set_attr "arch" "t2,*")
5071 (set_attr "length" "4")
5072 (set_attr "type" "mvn_reg")]
5073 )
5074
5075 (define_insn "*notsi_compare0"
5076 [(set (reg:CC_NOOV CC_REGNUM)
5077 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5078 (const_int 0)))
5079 (set (match_operand:SI 0 "s_register_operand" "=r")
5080 (not:SI (match_dup 1)))]
5081 "TARGET_32BIT"
5082 "mvns%?\\t%0, %1"
5083 [(set_attr "conds" "set")
5084 (set_attr "type" "mvn_reg")]
5085 )
5086
5087 (define_insn "*notsi_compare0_scratch"
5088 [(set (reg:CC_NOOV CC_REGNUM)
5089 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5090 (const_int 0)))
5091 (clobber (match_scratch:SI 0 "=r"))]
5092 "TARGET_32BIT"
5093 "mvns%?\\t%0, %1"
5094 [(set_attr "conds" "set")
5095 (set_attr "type" "mvn_reg")]
5096 )
5097 \f
5098 ;; Fixed <--> Floating conversion insns
5099
5100 (define_expand "floatsihf2"
5101 [(set (match_operand:HF 0 "general_operand" "")
5102 (float:HF (match_operand:SI 1 "general_operand" "")))]
5103 "TARGET_EITHER"
5104 "
5105 {
5106 rtx op1 = gen_reg_rtx (SFmode);
5107 expand_float (op1, operands[1], 0);
5108 op1 = convert_to_mode (HFmode, op1, 0);
5109 emit_move_insn (operands[0], op1);
5110 DONE;
5111 }"
5112 )
5113
5114 (define_expand "floatdihf2"
5115 [(set (match_operand:HF 0 "general_operand" "")
5116 (float:HF (match_operand:DI 1 "general_operand" "")))]
5117 "TARGET_EITHER"
5118 "
5119 {
5120 rtx op1 = gen_reg_rtx (SFmode);
5121 expand_float (op1, operands[1], 0);
5122 op1 = convert_to_mode (HFmode, op1, 0);
5123 emit_move_insn (operands[0], op1);
5124 DONE;
5125 }"
5126 )
5127
5128 (define_expand "floatsisf2"
5129 [(set (match_operand:SF 0 "s_register_operand" "")
5130 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
5131 "TARGET_32BIT && TARGET_HARD_FLOAT"
5132 "
5133 ")
5134
5135 (define_expand "floatsidf2"
5136 [(set (match_operand:DF 0 "s_register_operand" "")
5137 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
5138 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5139 "
5140 ")
5141
5142 (define_expand "fix_trunchfsi2"
5143 [(set (match_operand:SI 0 "general_operand" "")
5144 (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5145 "TARGET_EITHER"
5146 "
5147 {
5148 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5149 expand_fix (operands[0], op1, 0);
5150 DONE;
5151 }"
5152 )
5153
5154 (define_expand "fix_trunchfdi2"
5155 [(set (match_operand:DI 0 "general_operand" "")
5156 (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
5157 "TARGET_EITHER"
5158 "
5159 {
5160 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
5161 expand_fix (operands[0], op1, 0);
5162 DONE;
5163 }"
5164 )
5165
5166 (define_expand "fix_truncsfsi2"
5167 [(set (match_operand:SI 0 "s_register_operand" "")
5168 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
5169 "TARGET_32BIT && TARGET_HARD_FLOAT"
5170 "
5171 ")
5172
5173 (define_expand "fix_truncdfsi2"
5174 [(set (match_operand:SI 0 "s_register_operand" "")
5175 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
5176 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5177 "
5178 ")
5179
5180 ;; Truncation insns
5181
5182 (define_expand "truncdfsf2"
5183 [(set (match_operand:SF 0 "s_register_operand" "")
5184 (float_truncate:SF
5185 (match_operand:DF 1 "s_register_operand" "")))]
5186 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5187 ""
5188 )
5189
5190 ;; DFmode to HFmode conversions on targets without a single-step hardware
5191 ;; instruction for it would have to go through SFmode. This is dangerous
5192 ;; as it introduces double rounding.
5193 ;;
5194 ;; Disable this pattern unless we are in an unsafe math mode, or we have
5195 ;; a single-step instruction.
5196
5197 (define_expand "truncdfhf2"
5198 [(set (match_operand:HF 0 "s_register_operand" "")
5199 (float_truncate:HF
5200 (match_operand:DF 1 "s_register_operand" "")))]
5201 "(TARGET_EITHER && flag_unsafe_math_optimizations)
5202 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
5203 {
5204 /* We don't have a direct instruction for this, so we must be in
5205 an unsafe math mode, and going via SFmode. */
5206
5207 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5208 {
5209 rtx op1;
5210 op1 = convert_to_mode (SFmode, operands[1], 0);
5211 op1 = convert_to_mode (HFmode, op1, 0);
5212 emit_move_insn (operands[0], op1);
5213 DONE;
5214 }
5215 /* Otherwise, we will pick this up as a single instruction with
5216 no intermediary rounding. */
5217 }
5218 )
5219 \f
5220 ;; Zero and sign extension instructions.
5221
5222 (define_insn "zero_extend<mode>di2"
5223 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
5224 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
5225 "<qhs_zextenddi_cstr>")))]
5226 "TARGET_32BIT <qhs_zextenddi_cond>"
5227 "#"
5228 [(set_attr "length" "8,4,8,8")
5229 (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
5230 (set_attr "ce_count" "2")
5231 (set_attr "predicable" "yes")
5232 (set_attr "type" "multiple,mov_reg,multiple,multiple")]
5233 )
5234
5235 (define_insn "extend<mode>di2"
5236 [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
5237 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
5238 "<qhs_extenddi_cstr>")))]
5239 "TARGET_32BIT <qhs_sextenddi_cond>"
5240 "#"
5241 [(set_attr "length" "8,4,8,8,8")
5242 (set_attr "ce_count" "2")
5243 (set_attr "shift" "1")
5244 (set_attr "predicable" "yes")
5245 (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
5246 (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
5247 )
5248
5249 ;; Splits for all extensions to DImode
5250 (define_split
5251 [(set (match_operand:DI 0 "s_register_operand" "")
5252 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
5253 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
5254 [(set (match_dup 0) (match_dup 1))]
5255 {
5256 rtx lo_part = gen_lowpart (SImode, operands[0]);
5257 machine_mode src_mode = GET_MODE (operands[1]);
5258
5259 if (REG_P (operands[0])
5260 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5261 emit_clobber (operands[0]);
5262 if (!REG_P (lo_part) || src_mode != SImode
5263 || !rtx_equal_p (lo_part, operands[1]))
5264 {
5265 if (src_mode == SImode)
5266 emit_move_insn (lo_part, operands[1]);
5267 else
5268 emit_insn (gen_rtx_SET (lo_part,
5269 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
5270 operands[1] = lo_part;
5271 }
5272 operands[0] = gen_highpart (SImode, operands[0]);
5273 operands[1] = const0_rtx;
5274 })
5275
5276 (define_split
5277 [(set (match_operand:DI 0 "s_register_operand" "")
5278 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
5279 "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
5280 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
5281 {
5282 rtx lo_part = gen_lowpart (SImode, operands[0]);
5283 machine_mode src_mode = GET_MODE (operands[1]);
5284
5285 if (REG_P (operands[0])
5286 && !reg_overlap_mentioned_p (operands[0], operands[1]))
5287 emit_clobber (operands[0]);
5288
5289 if (!REG_P (lo_part) || src_mode != SImode
5290 || !rtx_equal_p (lo_part, operands[1]))
5291 {
5292 if (src_mode == SImode)
5293 emit_move_insn (lo_part, operands[1]);
5294 else
5295 emit_insn (gen_rtx_SET (lo_part,
5296 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
5297 operands[1] = lo_part;
5298 }
5299 operands[0] = gen_highpart (SImode, operands[0]);
5300 })
5301
5302 (define_expand "zero_extendhisi2"
5303 [(set (match_operand:SI 0 "s_register_operand" "")
5304 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
5305 "TARGET_EITHER"
5306 {
5307 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
5308 {
5309 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
5310 DONE;
5311 }
5312 if (!arm_arch6 && !MEM_P (operands[1]))
5313 {
5314 rtx t = gen_lowpart (SImode, operands[1]);
5315 rtx tmp = gen_reg_rtx (SImode);
5316 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5317 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
5318 DONE;
5319 }
5320 })
5321
5322 (define_split
5323 [(set (match_operand:SI 0 "s_register_operand" "")
5324 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
5325 "!TARGET_THUMB2 && !arm_arch6"
5326 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5327 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
5328 {
5329 operands[2] = gen_lowpart (SImode, operands[1]);
5330 })
5331
5332 (define_insn "*arm_zero_extendhisi2"
5333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5334 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
5335 "TARGET_ARM && arm_arch4 && !arm_arch6"
5336 "@
5337 #
5338 ldrh%?\\t%0, %1"
5339 [(set_attr "type" "alu_shift_reg,load_byte")
5340 (set_attr "predicable" "yes")]
5341 )
5342
5343 (define_insn "*arm_zero_extendhisi2_v6"
5344 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5345 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
5346 "TARGET_ARM && arm_arch6"
5347 "@
5348 uxth%?\\t%0, %1
5349 ldrh%?\\t%0, %1"
5350 [(set_attr "predicable" "yes")
5351 (set_attr "type" "extend,load_byte")]
5352 )
5353
5354 (define_insn "*arm_zero_extendhisi2addsi"
5355 [(set (match_operand:SI 0 "s_register_operand" "=r")
5356 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5357 (match_operand:SI 2 "s_register_operand" "r")))]
5358 "TARGET_INT_SIMD"
5359 "uxtah%?\\t%0, %2, %1"
5360 [(set_attr "type" "alu_shift_reg")
5361 (set_attr "predicable" "yes")
5362 (set_attr "predicable_short_it" "no")]
5363 )
5364
5365 (define_expand "zero_extendqisi2"
5366 [(set (match_operand:SI 0 "s_register_operand" "")
5367 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5368 "TARGET_EITHER"
5369 {
5370 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
5371 {
5372 emit_insn (gen_andsi3 (operands[0],
5373 gen_lowpart (SImode, operands[1]),
5374 GEN_INT (255)));
5375 DONE;
5376 }
5377 if (!arm_arch6 && !MEM_P (operands[1]))
5378 {
5379 rtx t = gen_lowpart (SImode, operands[1]);
5380 rtx tmp = gen_reg_rtx (SImode);
5381 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5382 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5383 DONE;
5384 }
5385 })
5386
5387 (define_split
5388 [(set (match_operand:SI 0 "s_register_operand" "")
5389 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
5390 "!arm_arch6"
5391 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5392 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5393 {
5394 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5395 if (TARGET_ARM)
5396 {
5397 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
5398 DONE;
5399 }
5400 })
5401
5402 (define_insn "*arm_zero_extendqisi2"
5403 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5404 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
5405 "TARGET_ARM && !arm_arch6"
5406 "@
5407 #
5408 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
5409 [(set_attr "length" "8,4")
5410 (set_attr "type" "alu_shift_reg,load_byte")
5411 (set_attr "predicable" "yes")]
5412 )
5413
5414 (define_insn "*arm_zero_extendqisi2_v6"
5415 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5416 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
5417 "TARGET_ARM && arm_arch6"
5418 "@
5419 uxtb%?\\t%0, %1
5420 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
5421 [(set_attr "type" "extend,load_byte")
5422 (set_attr "predicable" "yes")]
5423 )
5424
5425 (define_insn "*arm_zero_extendqisi2addsi"
5426 [(set (match_operand:SI 0 "s_register_operand" "=r")
5427 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5428 (match_operand:SI 2 "s_register_operand" "r")))]
5429 "TARGET_INT_SIMD"
5430 "uxtab%?\\t%0, %2, %1"
5431 [(set_attr "predicable" "yes")
5432 (set_attr "predicable_short_it" "no")
5433 (set_attr "type" "alu_shift_reg")]
5434 )
5435
5436 (define_split
5437 [(set (match_operand:SI 0 "s_register_operand" "")
5438 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5439 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5440 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
5441 [(set (match_dup 2) (match_dup 1))
5442 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5443 ""
5444 )
5445
5446 (define_split
5447 [(set (match_operand:SI 0 "s_register_operand" "")
5448 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5449 (clobber (match_operand:SI 2 "s_register_operand" ""))]
5450 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
5451 [(set (match_dup 2) (match_dup 1))
5452 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5453 ""
5454 )
5455
5456
5457 (define_split
5458 [(set (match_operand:SI 0 "s_register_operand" "")
5459 (IOR_XOR:SI (and:SI (ashift:SI
5460 (match_operand:SI 1 "s_register_operand" "")
5461 (match_operand:SI 2 "const_int_operand" ""))
5462 (match_operand:SI 3 "const_int_operand" ""))
5463 (zero_extend:SI
5464 (match_operator 5 "subreg_lowpart_operator"
5465 [(match_operand:SI 4 "s_register_operand" "")]))))]
5466 "TARGET_32BIT
5467 && (UINTVAL (operands[3])
5468 == (GET_MODE_MASK (GET_MODE (operands[5]))
5469 & (GET_MODE_MASK (GET_MODE (operands[5]))
5470 << (INTVAL (operands[2])))))"
5471 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
5472 (match_dup 4)))
5473 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5474 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5475 )
5476
5477 (define_insn "*compareqi_eq0"
5478 [(set (reg:CC_Z CC_REGNUM)
5479 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
5480 (const_int 0)))]
5481 "TARGET_32BIT"
5482 "tst%?\\t%0, #255"
5483 [(set_attr "conds" "set")
5484 (set_attr "predicable" "yes")
5485 (set_attr "predicable_short_it" "no")
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 (set_attr "predicable_short_it" "no")]
5597 )
5598
5599 (define_insn "*arm_extendhisi2addsi"
5600 [(set (match_operand:SI 0 "s_register_operand" "=r")
5601 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5602 (match_operand:SI 2 "s_register_operand" "r")))]
5603 "TARGET_INT_SIMD"
5604 "sxtah%?\\t%0, %2, %1"
5605 [(set_attr "type" "alu_shift_reg")]
5606 )
5607
5608 (define_expand "extendqihi2"
5609 [(set (match_dup 2)
5610 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
5611 (const_int 24)))
5612 (set (match_operand:HI 0 "s_register_operand" "")
5613 (ashiftrt:SI (match_dup 2)
5614 (const_int 24)))]
5615 "TARGET_ARM"
5616 "
5617 {
5618 if (arm_arch4 && MEM_P (operands[1]))
5619 {
5620 emit_insn (gen_rtx_SET (operands[0],
5621 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5622 DONE;
5623 }
5624 if (!s_register_operand (operands[1], QImode))
5625 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5626 operands[0] = gen_lowpart (SImode, operands[0]);
5627 operands[1] = gen_lowpart (SImode, operands[1]);
5628 operands[2] = gen_reg_rtx (SImode);
5629 }"
5630 )
5631
5632 (define_insn "*arm_extendqihi_insn"
5633 [(set (match_operand:HI 0 "s_register_operand" "=r")
5634 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
5635 "TARGET_ARM && arm_arch4"
5636 "ldrsb%?\\t%0, %1"
5637 [(set_attr "type" "load_byte")
5638 (set_attr "predicable" "yes")]
5639 )
5640
5641 (define_expand "extendqisi2"
5642 [(set (match_operand:SI 0 "s_register_operand" "")
5643 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
5644 "TARGET_EITHER"
5645 {
5646 if (!arm_arch4 && MEM_P (operands[1]))
5647 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5648
5649 if (!arm_arch6 && !MEM_P (operands[1]))
5650 {
5651 rtx t = gen_lowpart (SImode, operands[1]);
5652 rtx tmp = gen_reg_rtx (SImode);
5653 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5654 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5655 DONE;
5656 }
5657 })
5658
5659 (define_split
5660 [(set (match_operand:SI 0 "register_operand" "")
5661 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5662 "!arm_arch6"
5663 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5664 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5665 {
5666 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5667 })
5668
5669 (define_insn "*arm_extendqisi"
5670 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5671 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5672 "TARGET_ARM && arm_arch4 && !arm_arch6"
5673 "@
5674 #
5675 ldrsb%?\\t%0, %1"
5676 [(set_attr "length" "8,4")
5677 (set_attr "type" "alu_shift_reg,load_byte")
5678 (set_attr "predicable" "yes")]
5679 )
5680
5681 (define_insn "*arm_extendqisi_v6"
5682 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5683 (sign_extend:SI
5684 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5685 "TARGET_ARM && arm_arch6"
5686 "@
5687 sxtb%?\\t%0, %1
5688 ldrsb%?\\t%0, %1"
5689 [(set_attr "type" "extend,load_byte")
5690 (set_attr "predicable" "yes")]
5691 )
5692
5693 (define_insn "*arm_extendqisi2addsi"
5694 [(set (match_operand:SI 0 "s_register_operand" "=r")
5695 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5696 (match_operand:SI 2 "s_register_operand" "r")))]
5697 "TARGET_INT_SIMD"
5698 "sxtab%?\\t%0, %2, %1"
5699 [(set_attr "type" "alu_shift_reg")
5700 (set_attr "predicable" "yes")
5701 (set_attr "predicable_short_it" "no")]
5702 )
5703
5704 (define_expand "extendsfdf2"
5705 [(set (match_operand:DF 0 "s_register_operand" "")
5706 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
5707 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5708 ""
5709 )
5710
5711 ;; HFmode -> DFmode conversions where we don't have an instruction for it
5712 ;; must go through SFmode.
5713 ;;
5714 ;; This is always safe for an extend.
5715
5716 (define_expand "extendhfdf2"
5717 [(set (match_operand:DF 0 "s_register_operand" "")
5718 (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
5719 "TARGET_EITHER"
5720 {
5721 /* We don't have a direct instruction for this, so go via SFmode. */
5722 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5723 {
5724 rtx op1;
5725 op1 = convert_to_mode (SFmode, operands[1], 0);
5726 op1 = convert_to_mode (DFmode, op1, 0);
5727 emit_insn (gen_movdf (operands[0], op1));
5728 DONE;
5729 }
5730 /* Otherwise, we're done producing RTL and will pick up the correct
5731 pattern to do this with one rounding-step in a single instruction. */
5732 }
5733 )
5734 \f
5735 ;; Move insns (including loads and stores)
5736
5737 ;; XXX Just some ideas about movti.
5738 ;; I don't think these are a good idea on the arm, there just aren't enough
5739 ;; registers
5740 ;;(define_expand "loadti"
5741 ;; [(set (match_operand:TI 0 "s_register_operand" "")
5742 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5743 ;; "" "")
5744
5745 ;;(define_expand "storeti"
5746 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
5747 ;; (match_operand:TI 1 "s_register_operand" ""))]
5748 ;; "" "")
5749
5750 ;;(define_expand "movti"
5751 ;; [(set (match_operand:TI 0 "general_operand" "")
5752 ;; (match_operand:TI 1 "general_operand" ""))]
5753 ;; ""
5754 ;; "
5755 ;;{
5756 ;; rtx insn;
5757 ;;
5758 ;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
5759 ;; operands[1] = copy_to_reg (operands[1]);
5760 ;; if (MEM_P (operands[0]))
5761 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5762 ;; else if (MEM_P (operands[1]))
5763 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5764 ;; else
5765 ;; FAIL;
5766 ;;
5767 ;; emit_insn (insn);
5768 ;; DONE;
5769 ;;}")
5770
5771 ;; Recognize garbage generated above.
5772
5773 ;;(define_insn ""
5774 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5775 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5776 ;; ""
5777 ;; "*
5778 ;; {
5779 ;; register mem = (which_alternative < 3);
5780 ;; register const char *template;
5781 ;;
5782 ;; operands[mem] = XEXP (operands[mem], 0);
5783 ;; switch (which_alternative)
5784 ;; {
5785 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5786 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5787 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5788 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5789 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5790 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
5791 ;; }
5792 ;; output_asm_insn (template, operands);
5793 ;; return \"\";
5794 ;; }")
5795
5796 (define_expand "movdi"
5797 [(set (match_operand:DI 0 "general_operand" "")
5798 (match_operand:DI 1 "general_operand" ""))]
5799 "TARGET_EITHER"
5800 "
5801 if (can_create_pseudo_p ())
5802 {
5803 if (!REG_P (operands[0]))
5804 operands[1] = force_reg (DImode, operands[1]);
5805 }
5806 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
5807 && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
5808 {
5809 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5810 when expanding function calls. */
5811 gcc_assert (can_create_pseudo_p ());
5812 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5813 {
5814 /* Perform load into legal reg pair first, then move. */
5815 rtx reg = gen_reg_rtx (DImode);
5816 emit_insn (gen_movdi (reg, operands[1]));
5817 operands[1] = reg;
5818 }
5819 emit_move_insn (gen_lowpart (SImode, operands[0]),
5820 gen_lowpart (SImode, operands[1]));
5821 emit_move_insn (gen_highpart (SImode, operands[0]),
5822 gen_highpart (SImode, operands[1]));
5823 DONE;
5824 }
5825 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
5826 && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
5827 {
5828 /* Avoid STRD's from an odd-numbered register pair in ARM state
5829 when expanding function prologue. */
5830 gcc_assert (can_create_pseudo_p ());
5831 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5832 ? gen_reg_rtx (DImode)
5833 : operands[0];
5834 emit_move_insn (gen_lowpart (SImode, split_dest),
5835 gen_lowpart (SImode, operands[1]));
5836 emit_move_insn (gen_highpart (SImode, split_dest),
5837 gen_highpart (SImode, operands[1]));
5838 if (split_dest != operands[0])
5839 emit_insn (gen_movdi (operands[0], split_dest));
5840 DONE;
5841 }
5842 "
5843 )
5844
5845 (define_insn "*arm_movdi"
5846 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5847 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
5848 "TARGET_32BIT
5849 && !(TARGET_HARD_FLOAT)
5850 && !TARGET_IWMMXT
5851 && ( register_operand (operands[0], DImode)
5852 || register_operand (operands[1], DImode))"
5853 "*
5854 switch (which_alternative)
5855 {
5856 case 0:
5857 case 1:
5858 case 2:
5859 return \"#\";
5860 default:
5861 return output_move_double (operands, true, NULL);
5862 }
5863 "
5864 [(set_attr "length" "8,12,16,8,8")
5865 (set_attr "type" "multiple,multiple,multiple,load2,store2")
5866 (set_attr "arm_pool_range" "*,*,*,1020,*")
5867 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5868 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
5869 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5870 )
5871
5872 (define_split
5873 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5874 (match_operand:ANY64 1 "immediate_operand" ""))]
5875 "TARGET_32BIT
5876 && reload_completed
5877 && (arm_disable_literal_pool
5878 || (arm_const_double_inline_cost (operands[1])
5879 <= arm_max_const_double_inline_cost ()))"
5880 [(const_int 0)]
5881 "
5882 arm_split_constant (SET, SImode, curr_insn,
5883 INTVAL (gen_lowpart (SImode, operands[1])),
5884 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5885 arm_split_constant (SET, SImode, curr_insn,
5886 INTVAL (gen_highpart_mode (SImode,
5887 GET_MODE (operands[0]),
5888 operands[1])),
5889 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5890 DONE;
5891 "
5892 )
5893
5894 ; If optimizing for size, or if we have load delay slots, then
5895 ; we want to split the constant into two separate operations.
5896 ; In both cases this may split a trivial part into a single data op
5897 ; leaving a single complex constant to load. We can also get longer
5898 ; offsets in a LDR which means we get better chances of sharing the pool
5899 ; entries. Finally, we can normally do a better job of scheduling
5900 ; LDR instructions than we can with LDM.
5901 ; This pattern will only match if the one above did not.
5902 (define_split
5903 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5904 (match_operand:ANY64 1 "const_double_operand" ""))]
5905 "TARGET_ARM && reload_completed
5906 && arm_const_double_by_parts (operands[1])"
5907 [(set (match_dup 0) (match_dup 1))
5908 (set (match_dup 2) (match_dup 3))]
5909 "
5910 operands[2] = gen_highpart (SImode, operands[0]);
5911 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5912 operands[1]);
5913 operands[0] = gen_lowpart (SImode, operands[0]);
5914 operands[1] = gen_lowpart (SImode, operands[1]);
5915 "
5916 )
5917
5918 (define_split
5919 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5920 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5921 "TARGET_EITHER && reload_completed"
5922 [(set (match_dup 0) (match_dup 1))
5923 (set (match_dup 2) (match_dup 3))]
5924 "
5925 operands[2] = gen_highpart (SImode, operands[0]);
5926 operands[3] = gen_highpart (SImode, operands[1]);
5927 operands[0] = gen_lowpart (SImode, operands[0]);
5928 operands[1] = gen_lowpart (SImode, operands[1]);
5929
5930 /* Handle a partial overlap. */
5931 if (rtx_equal_p (operands[0], operands[3]))
5932 {
5933 rtx tmp0 = operands[0];
5934 rtx tmp1 = operands[1];
5935
5936 operands[0] = operands[2];
5937 operands[1] = operands[3];
5938 operands[2] = tmp0;
5939 operands[3] = tmp1;
5940 }
5941 "
5942 )
5943
5944 ;; We can't actually do base+index doubleword loads if the index and
5945 ;; destination overlap. Split here so that we at least have chance to
5946 ;; schedule.
5947 (define_split
5948 [(set (match_operand:DI 0 "s_register_operand" "")
5949 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5950 (match_operand:SI 2 "s_register_operand" ""))))]
5951 "TARGET_LDRD
5952 && reg_overlap_mentioned_p (operands[0], operands[1])
5953 && reg_overlap_mentioned_p (operands[0], operands[2])"
5954 [(set (match_dup 4)
5955 (plus:SI (match_dup 1)
5956 (match_dup 2)))
5957 (set (match_dup 0)
5958 (mem:DI (match_dup 4)))]
5959 "
5960 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5961 "
5962 )
5963
5964 (define_expand "movsi"
5965 [(set (match_operand:SI 0 "general_operand" "")
5966 (match_operand:SI 1 "general_operand" ""))]
5967 "TARGET_EITHER"
5968 "
5969 {
5970 rtx base, offset, tmp;
5971
5972 if (TARGET_32BIT || TARGET_HAVE_MOVT)
5973 {
5974 /* Everything except mem = const or mem = mem can be done easily. */
5975 if (MEM_P (operands[0]))
5976 operands[1] = force_reg (SImode, operands[1]);
5977 if (arm_general_register_operand (operands[0], SImode)
5978 && CONST_INT_P (operands[1])
5979 && !(const_ok_for_arm (INTVAL (operands[1]))
5980 || const_ok_for_arm (~INTVAL (operands[1]))))
5981 {
5982 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5983 {
5984 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5985 DONE;
5986 }
5987 else
5988 {
5989 arm_split_constant (SET, SImode, NULL_RTX,
5990 INTVAL (operands[1]), operands[0], NULL_RTX,
5991 optimize && can_create_pseudo_p ());
5992 DONE;
5993 }
5994 }
5995 }
5996 else /* Target doesn't have MOVT... */
5997 {
5998 if (can_create_pseudo_p ())
5999 {
6000 if (!REG_P (operands[0]))
6001 operands[1] = force_reg (SImode, operands[1]);
6002 }
6003 }
6004
6005 if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
6006 {
6007 split_const (operands[1], &base, &offset);
6008 if (GET_CODE (base) == SYMBOL_REF
6009 && !offset_within_block_p (base, INTVAL (offset)))
6010 {
6011 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
6012 emit_move_insn (tmp, base);
6013 emit_insn (gen_addsi3 (operands[0], tmp, offset));
6014 DONE;
6015 }
6016 }
6017
6018 /* Recognize the case where operand[1] is a reference to thread-local
6019 data and load its address to a register. */
6020 if (arm_tls_referenced_p (operands[1]))
6021 {
6022 rtx tmp = operands[1];
6023 rtx addend = NULL;
6024
6025 if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
6026 {
6027 addend = XEXP (XEXP (tmp, 0), 1);
6028 tmp = XEXP (XEXP (tmp, 0), 0);
6029 }
6030
6031 gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
6032 gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
6033
6034 tmp = legitimize_tls_address (tmp,
6035 !can_create_pseudo_p () ? operands[0] : 0);
6036 if (addend)
6037 {
6038 tmp = gen_rtx_PLUS (SImode, tmp, addend);
6039 tmp = force_operand (tmp, operands[0]);
6040 }
6041 operands[1] = tmp;
6042 }
6043 else if (flag_pic
6044 && (CONSTANT_P (operands[1])
6045 || symbol_mentioned_p (operands[1])
6046 || label_mentioned_p (operands[1])))
6047 operands[1] = legitimize_pic_address (operands[1], SImode,
6048 (!can_create_pseudo_p ()
6049 ? operands[0]
6050 : 0));
6051 }
6052 "
6053 )
6054
6055 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
6056 ;; LO_SUM adds in the high bits. Fortunately these are opaque operations
6057 ;; so this does not matter.
6058 (define_insn "*arm_movt"
6059 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
6060 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
6061 (match_operand:SI 2 "general_operand" "i,i")))]
6062 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
6063 "@
6064 movt%?\t%0, #:upper16:%c2
6065 movt\t%0, #:upper16:%c2"
6066 [(set_attr "arch" "32,v8mb")
6067 (set_attr "predicable" "yes")
6068 (set_attr "predicable_short_it" "no")
6069 (set_attr "length" "4")
6070 (set_attr "type" "alu_sreg")]
6071 )
6072
6073 (define_insn "*arm_movsi_insn"
6074 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
6075 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
6076 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
6077 && ( register_operand (operands[0], SImode)
6078 || register_operand (operands[1], SImode))"
6079 "@
6080 mov%?\\t%0, %1
6081 mov%?\\t%0, %1
6082 mvn%?\\t%0, #%B1
6083 movw%?\\t%0, %1
6084 ldr%?\\t%0, %1
6085 str%?\\t%1, %0"
6086 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
6087 (set_attr "predicable" "yes")
6088 (set_attr "arch" "*,*,*,v6t2,*,*")
6089 (set_attr "pool_range" "*,*,*,*,4096,*")
6090 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
6091 )
6092
6093 (define_split
6094 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6095 (match_operand:SI 1 "const_int_operand" ""))]
6096 "(TARGET_32BIT || TARGET_HAVE_MOVT)
6097 && (!(const_ok_for_arm (INTVAL (operands[1]))
6098 || const_ok_for_arm (~INTVAL (operands[1]))))"
6099 [(clobber (const_int 0))]
6100 "
6101 arm_split_constant (SET, SImode, NULL_RTX,
6102 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
6103 DONE;
6104 "
6105 )
6106
6107 ;; A normal way to do (symbol + offset) requires three instructions at least
6108 ;; (depends on how big the offset is) as below:
6109 ;; movw r0, #:lower16:g
6110 ;; movw r0, #:upper16:g
6111 ;; adds r0, #4
6112 ;;
6113 ;; A better way would be:
6114 ;; movw r0, #:lower16:g+4
6115 ;; movw r0, #:upper16:g+4
6116 ;;
6117 ;; The limitation of this way is that the length of offset should be a 16-bit
6118 ;; signed value, because current assembler only supports REL type relocation for
6119 ;; such case. If the more powerful RELA type is supported in future, we should
6120 ;; update this pattern to go with better way.
6121 (define_split
6122 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6123 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
6124 (match_operand:SI 2 "const_int_operand" ""))))]
6125 "TARGET_THUMB
6126 && TARGET_HAVE_MOVT
6127 && arm_disable_literal_pool
6128 && reload_completed
6129 && GET_CODE (operands[1]) == SYMBOL_REF"
6130 [(clobber (const_int 0))]
6131 "
6132 int offset = INTVAL (operands[2]);
6133
6134 if (offset < -0x8000 || offset > 0x7fff)
6135 {
6136 arm_emit_movpair (operands[0], operands[1]);
6137 emit_insn (gen_rtx_SET (operands[0],
6138 gen_rtx_PLUS (SImode, operands[0], operands[2])));
6139 }
6140 else
6141 {
6142 rtx op = gen_rtx_CONST (SImode,
6143 gen_rtx_PLUS (SImode, operands[1], operands[2]));
6144 arm_emit_movpair (operands[0], op);
6145 }
6146 "
6147 )
6148
6149 ;; Split symbol_refs at the later stage (after cprop), instead of generating
6150 ;; movt/movw pair directly at expand. Otherwise corresponding high_sum
6151 ;; and lo_sum would be merged back into memory load at cprop. However,
6152 ;; if the default is to prefer movt/movw rather than a load from the constant
6153 ;; pool, the performance is better.
6154 (define_split
6155 [(set (match_operand:SI 0 "arm_general_register_operand" "")
6156 (match_operand:SI 1 "general_operand" ""))]
6157 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
6158 && !flag_pic && !target_word_relocations
6159 && !arm_tls_referenced_p (operands[1])"
6160 [(clobber (const_int 0))]
6161 {
6162 arm_emit_movpair (operands[0], operands[1]);
6163 DONE;
6164 })
6165
6166 ;; When generating pic, we need to load the symbol offset into a register.
6167 ;; So that the optimizer does not confuse this with a normal symbol load
6168 ;; we use an unspec. The offset will be loaded from a constant pool entry,
6169 ;; since that is the only type of relocation we can use.
6170
6171 ;; Wrap calculation of the whole PIC address in a single pattern for the
6172 ;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
6173 ;; a PIC address involves two loads from memory, so we want to CSE it
6174 ;; as often as possible.
6175 ;; This pattern will be split into one of the pic_load_addr_* patterns
6176 ;; and a move after GCSE optimizations.
6177 ;;
6178 ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
6179 (define_expand "calculate_pic_address"
6180 [(set (match_operand:SI 0 "register_operand" "")
6181 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6182 (unspec:SI [(match_operand:SI 2 "" "")]
6183 UNSPEC_PIC_SYM))))]
6184 "flag_pic"
6185 )
6186
6187 ;; Split calculate_pic_address into pic_load_addr_* and a move.
6188 (define_split
6189 [(set (match_operand:SI 0 "register_operand" "")
6190 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
6191 (unspec:SI [(match_operand:SI 2 "" "")]
6192 UNSPEC_PIC_SYM))))]
6193 "flag_pic"
6194 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
6195 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
6196 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
6197 )
6198
6199 ;; operand1 is the memory address to go into
6200 ;; pic_load_addr_32bit.
6201 ;; operand2 is the PIC label to be emitted
6202 ;; from pic_add_dot_plus_eight.
6203 ;; We do this to allow hoisting of the entire insn.
6204 (define_insn_and_split "pic_load_addr_unified"
6205 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
6206 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
6207 (match_operand:SI 2 "" "")]
6208 UNSPEC_PIC_UNIFIED))]
6209 "flag_pic"
6210 "#"
6211 "&& reload_completed"
6212 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
6213 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
6214 (match_dup 2)] UNSPEC_PIC_BASE))]
6215 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
6216 [(set_attr "type" "load1,load1,load1")
6217 (set_attr "pool_range" "4096,4094,1022")
6218 (set_attr "neg_pool_range" "4084,0,0")
6219 (set_attr "arch" "a,t2,t1")
6220 (set_attr "length" "8,6,4")]
6221 )
6222
6223 ;; The rather odd constraints on the following are to force reload to leave
6224 ;; the insn alone, and to force the minipool generation pass to then move
6225 ;; the GOT symbol to memory.
6226
6227 (define_insn "pic_load_addr_32bit"
6228 [(set (match_operand:SI 0 "s_register_operand" "=r")
6229 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
6230 "TARGET_32BIT && flag_pic"
6231 "ldr%?\\t%0, %1"
6232 [(set_attr "type" "load1")
6233 (set (attr "pool_range")
6234 (if_then_else (eq_attr "is_thumb" "no")
6235 (const_int 4096)
6236 (const_int 4094)))
6237 (set (attr "neg_pool_range")
6238 (if_then_else (eq_attr "is_thumb" "no")
6239 (const_int 4084)
6240 (const_int 0)))]
6241 )
6242
6243 (define_insn "pic_load_addr_thumb1"
6244 [(set (match_operand:SI 0 "s_register_operand" "=l")
6245 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
6246 "TARGET_THUMB1 && flag_pic"
6247 "ldr\\t%0, %1"
6248 [(set_attr "type" "load1")
6249 (set (attr "pool_range") (const_int 1018))]
6250 )
6251
6252 (define_insn "pic_add_dot_plus_four"
6253 [(set (match_operand:SI 0 "register_operand" "=r")
6254 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
6255 (const_int 4)
6256 (match_operand 2 "" "")]
6257 UNSPEC_PIC_BASE))]
6258 "TARGET_THUMB"
6259 "*
6260 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6261 INTVAL (operands[2]));
6262 return \"add\\t%0, %|pc\";
6263 "
6264 [(set_attr "length" "2")
6265 (set_attr "type" "alu_sreg")]
6266 )
6267
6268 (define_insn "pic_add_dot_plus_eight"
6269 [(set (match_operand:SI 0 "register_operand" "=r")
6270 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6271 (const_int 8)
6272 (match_operand 2 "" "")]
6273 UNSPEC_PIC_BASE))]
6274 "TARGET_ARM"
6275 "*
6276 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6277 INTVAL (operands[2]));
6278 return \"add%?\\t%0, %|pc, %1\";
6279 "
6280 [(set_attr "predicable" "yes")
6281 (set_attr "type" "alu_sreg")]
6282 )
6283
6284 (define_insn "tls_load_dot_plus_eight"
6285 [(set (match_operand:SI 0 "register_operand" "=r")
6286 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
6287 (const_int 8)
6288 (match_operand 2 "" "")]
6289 UNSPEC_PIC_BASE)))]
6290 "TARGET_ARM"
6291 "*
6292 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
6293 INTVAL (operands[2]));
6294 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
6295 "
6296 [(set_attr "predicable" "yes")
6297 (set_attr "type" "load1")]
6298 )
6299
6300 ;; PIC references to local variables can generate pic_add_dot_plus_eight
6301 ;; followed by a load. These sequences can be crunched down to
6302 ;; tls_load_dot_plus_eight by a peephole.
6303
6304 (define_peephole2
6305 [(set (match_operand:SI 0 "register_operand" "")
6306 (unspec:SI [(match_operand:SI 3 "register_operand" "")
6307 (const_int 8)
6308 (match_operand 1 "" "")]
6309 UNSPEC_PIC_BASE))
6310 (set (match_operand:SI 2 "arm_general_register_operand" "")
6311 (mem:SI (match_dup 0)))]
6312 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
6313 [(set (match_dup 2)
6314 (mem:SI (unspec:SI [(match_dup 3)
6315 (const_int 8)
6316 (match_dup 1)]
6317 UNSPEC_PIC_BASE)))]
6318 ""
6319 )
6320
6321 (define_insn "pic_offset_arm"
6322 [(set (match_operand:SI 0 "register_operand" "=r")
6323 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
6324 (unspec:SI [(match_operand:SI 2 "" "X")]
6325 UNSPEC_PIC_OFFSET))))]
6326 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
6327 "ldr%?\\t%0, [%1,%2]"
6328 [(set_attr "type" "load1")]
6329 )
6330
6331 (define_expand "builtin_setjmp_receiver"
6332 [(label_ref (match_operand 0 "" ""))]
6333 "flag_pic"
6334 "
6335 {
6336 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
6337 register. */
6338 if (arm_pic_register != INVALID_REGNUM)
6339 arm_load_pic_register (1UL << 3);
6340 DONE;
6341 }")
6342
6343 ;; If copying one reg to another we can set the condition codes according to
6344 ;; its value. Such a move is common after a return from subroutine and the
6345 ;; result is being tested against zero.
6346
6347 (define_insn "*movsi_compare0"
6348 [(set (reg:CC CC_REGNUM)
6349 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
6350 (const_int 0)))
6351 (set (match_operand:SI 0 "s_register_operand" "=r,r")
6352 (match_dup 1))]
6353 "TARGET_32BIT"
6354 "@
6355 cmp%?\\t%0, #0
6356 subs%?\\t%0, %1, #0"
6357 [(set_attr "conds" "set")
6358 (set_attr "type" "alus_imm,alus_imm")]
6359 )
6360
6361 ;; Subroutine to store a half word from a register into memory.
6362 ;; Operand 0 is the source register (HImode)
6363 ;; Operand 1 is the destination address in a register (SImode)
6364
6365 ;; In both this routine and the next, we must be careful not to spill
6366 ;; a memory address of reg+large_const into a separate PLUS insn, since this
6367 ;; can generate unrecognizable rtl.
6368
6369 (define_expand "storehi"
6370 [;; store the low byte
6371 (set (match_operand 1 "" "") (match_dup 3))
6372 ;; extract the high byte
6373 (set (match_dup 2)
6374 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
6375 ;; store the high byte
6376 (set (match_dup 4) (match_dup 5))]
6377 "TARGET_ARM"
6378 "
6379 {
6380 rtx op1 = operands[1];
6381 rtx addr = XEXP (op1, 0);
6382 enum rtx_code code = GET_CODE (addr);
6383
6384 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
6385 || code == MINUS)
6386 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
6387
6388 operands[4] = adjust_address (op1, QImode, 1);
6389 operands[1] = adjust_address (operands[1], QImode, 0);
6390 operands[3] = gen_lowpart (QImode, operands[0]);
6391 operands[0] = gen_lowpart (SImode, operands[0]);
6392 operands[2] = gen_reg_rtx (SImode);
6393 operands[5] = gen_lowpart (QImode, operands[2]);
6394 }"
6395 )
6396
6397 (define_expand "storehi_bigend"
6398 [(set (match_dup 4) (match_dup 3))
6399 (set (match_dup 2)
6400 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
6401 (set (match_operand 1 "" "") (match_dup 5))]
6402 "TARGET_ARM"
6403 "
6404 {
6405 rtx op1 = operands[1];
6406 rtx addr = XEXP (op1, 0);
6407 enum rtx_code code = GET_CODE (addr);
6408
6409 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
6410 || code == MINUS)
6411 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
6412
6413 operands[4] = adjust_address (op1, QImode, 1);
6414 operands[1] = adjust_address (operands[1], QImode, 0);
6415 operands[3] = gen_lowpart (QImode, operands[0]);
6416 operands[0] = gen_lowpart (SImode, operands[0]);
6417 operands[2] = gen_reg_rtx (SImode);
6418 operands[5] = gen_lowpart (QImode, operands[2]);
6419 }"
6420 )
6421
6422 ;; Subroutine to store a half word integer constant into memory.
6423 (define_expand "storeinthi"
6424 [(set (match_operand 0 "" "")
6425 (match_operand 1 "" ""))
6426 (set (match_dup 3) (match_dup 2))]
6427 "TARGET_ARM"
6428 "
6429 {
6430 HOST_WIDE_INT value = INTVAL (operands[1]);
6431 rtx addr = XEXP (operands[0], 0);
6432 rtx op0 = operands[0];
6433 enum rtx_code code = GET_CODE (addr);
6434
6435 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
6436 || code == MINUS)
6437 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
6438
6439 operands[1] = gen_reg_rtx (SImode);
6440 if (BYTES_BIG_ENDIAN)
6441 {
6442 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6443 if ((value & 255) == ((value >> 8) & 255))
6444 operands[2] = operands[1];
6445 else
6446 {
6447 operands[2] = gen_reg_rtx (SImode);
6448 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6449 }
6450 }
6451 else
6452 {
6453 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6454 if ((value & 255) == ((value >> 8) & 255))
6455 operands[2] = operands[1];
6456 else
6457 {
6458 operands[2] = gen_reg_rtx (SImode);
6459 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6460 }
6461 }
6462
6463 operands[3] = adjust_address (op0, QImode, 1);
6464 operands[0] = adjust_address (operands[0], QImode, 0);
6465 operands[2] = gen_lowpart (QImode, operands[2]);
6466 operands[1] = gen_lowpart (QImode, operands[1]);
6467 }"
6468 )
6469
6470 (define_expand "storehi_single_op"
6471 [(set (match_operand:HI 0 "memory_operand" "")
6472 (match_operand:HI 1 "general_operand" ""))]
6473 "TARGET_32BIT && arm_arch4"
6474 "
6475 if (!s_register_operand (operands[1], HImode))
6476 operands[1] = copy_to_mode_reg (HImode, operands[1]);
6477 "
6478 )
6479
6480 (define_expand "movhi"
6481 [(set (match_operand:HI 0 "general_operand" "")
6482 (match_operand:HI 1 "general_operand" ""))]
6483 "TARGET_EITHER"
6484 "
6485 if (TARGET_ARM)
6486 {
6487 if (can_create_pseudo_p ())
6488 {
6489 if (MEM_P (operands[0]))
6490 {
6491 if (arm_arch4)
6492 {
6493 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6494 DONE;
6495 }
6496 if (CONST_INT_P (operands[1]))
6497 emit_insn (gen_storeinthi (operands[0], operands[1]));
6498 else
6499 {
6500 if (MEM_P (operands[1]))
6501 operands[1] = force_reg (HImode, operands[1]);
6502 if (BYTES_BIG_ENDIAN)
6503 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6504 else
6505 emit_insn (gen_storehi (operands[1], operands[0]));
6506 }
6507 DONE;
6508 }
6509 /* Sign extend a constant, and keep it in an SImode reg. */
6510 else if (CONST_INT_P (operands[1]))
6511 {
6512 rtx reg = gen_reg_rtx (SImode);
6513 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6514
6515 /* If the constant is already valid, leave it alone. */
6516 if (!const_ok_for_arm (val))
6517 {
6518 /* If setting all the top bits will make the constant
6519 loadable in a single instruction, then set them.
6520 Otherwise, sign extend the number. */
6521
6522 if (const_ok_for_arm (~(val | ~0xffff)))
6523 val |= ~0xffff;
6524 else if (val & 0x8000)
6525 val |= ~0xffff;
6526 }
6527
6528 emit_insn (gen_movsi (reg, GEN_INT (val)));
6529 operands[1] = gen_lowpart (HImode, reg);
6530 }
6531 else if (arm_arch4 && optimize && can_create_pseudo_p ()
6532 && MEM_P (operands[1]))
6533 {
6534 rtx reg = gen_reg_rtx (SImode);
6535
6536 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6537 operands[1] = gen_lowpart (HImode, reg);
6538 }
6539 else if (!arm_arch4)
6540 {
6541 if (MEM_P (operands[1]))
6542 {
6543 rtx base;
6544 rtx offset = const0_rtx;
6545 rtx reg = gen_reg_rtx (SImode);
6546
6547 if ((REG_P (base = XEXP (operands[1], 0))
6548 || (GET_CODE (base) == PLUS
6549 && (CONST_INT_P (offset = XEXP (base, 1)))
6550 && ((INTVAL(offset) & 1) != 1)
6551 && REG_P (base = XEXP (base, 0))))
6552 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
6553 {
6554 rtx new_rtx;
6555
6556 new_rtx = widen_memory_access (operands[1], SImode,
6557 ((INTVAL (offset) & ~3)
6558 - INTVAL (offset)));
6559 emit_insn (gen_movsi (reg, new_rtx));
6560 if (((INTVAL (offset) & 2) != 0)
6561 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6562 {
6563 rtx reg2 = gen_reg_rtx (SImode);
6564
6565 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6566 reg = reg2;
6567 }
6568 }
6569 else
6570 emit_insn (gen_movhi_bytes (reg, operands[1]));
6571
6572 operands[1] = gen_lowpart (HImode, reg);
6573 }
6574 }
6575 }
6576 /* Handle loading a large integer during reload. */
6577 else if (CONST_INT_P (operands[1])
6578 && !const_ok_for_arm (INTVAL (operands[1]))
6579 && !const_ok_for_arm (~INTVAL (operands[1])))
6580 {
6581 /* Writing a constant to memory needs a scratch, which should
6582 be handled with SECONDARY_RELOADs. */
6583 gcc_assert (REG_P (operands[0]));
6584
6585 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6586 emit_insn (gen_movsi (operands[0], operands[1]));
6587 DONE;
6588 }
6589 }
6590 else if (TARGET_THUMB2)
6591 {
6592 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
6593 if (can_create_pseudo_p ())
6594 {
6595 if (!REG_P (operands[0]))
6596 operands[1] = force_reg (HImode, operands[1]);
6597 /* Zero extend a constant, and keep it in an SImode reg. */
6598 else if (CONST_INT_P (operands[1]))
6599 {
6600 rtx reg = gen_reg_rtx (SImode);
6601 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6602
6603 emit_insn (gen_movsi (reg, GEN_INT (val)));
6604 operands[1] = gen_lowpart (HImode, reg);
6605 }
6606 }
6607 }
6608 else /* TARGET_THUMB1 */
6609 {
6610 if (can_create_pseudo_p ())
6611 {
6612 if (CONST_INT_P (operands[1]))
6613 {
6614 rtx reg = gen_reg_rtx (SImode);
6615
6616 emit_insn (gen_movsi (reg, operands[1]));
6617 operands[1] = gen_lowpart (HImode, reg);
6618 }
6619
6620 /* ??? We shouldn't really get invalid addresses here, but this can
6621 happen if we are passed a SP (never OK for HImode/QImode) or
6622 virtual register (also rejected as illegitimate for HImode/QImode)
6623 relative address. */
6624 /* ??? This should perhaps be fixed elsewhere, for instance, in
6625 fixup_stack_1, by checking for other kinds of invalid addresses,
6626 e.g. a bare reference to a virtual register. This may confuse the
6627 alpha though, which must handle this case differently. */
6628 if (MEM_P (operands[0])
6629 && !memory_address_p (GET_MODE (operands[0]),
6630 XEXP (operands[0], 0)))
6631 operands[0]
6632 = replace_equiv_address (operands[0],
6633 copy_to_reg (XEXP (operands[0], 0)));
6634
6635 if (MEM_P (operands[1])
6636 && !memory_address_p (GET_MODE (operands[1]),
6637 XEXP (operands[1], 0)))
6638 operands[1]
6639 = replace_equiv_address (operands[1],
6640 copy_to_reg (XEXP (operands[1], 0)));
6641
6642 if (MEM_P (operands[1]) && optimize > 0)
6643 {
6644 rtx reg = gen_reg_rtx (SImode);
6645
6646 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6647 operands[1] = gen_lowpart (HImode, reg);
6648 }
6649
6650 if (MEM_P (operands[0]))
6651 operands[1] = force_reg (HImode, operands[1]);
6652 }
6653 else if (CONST_INT_P (operands[1])
6654 && !satisfies_constraint_I (operands[1]))
6655 {
6656 /* Handle loading a large integer during reload. */
6657
6658 /* Writing a constant to memory needs a scratch, which should
6659 be handled with SECONDARY_RELOADs. */
6660 gcc_assert (REG_P (operands[0]));
6661
6662 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6663 emit_insn (gen_movsi (operands[0], operands[1]));
6664 DONE;
6665 }
6666 }
6667 "
6668 )
6669
6670 (define_expand "movhi_bytes"
6671 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6672 (set (match_dup 3)
6673 (zero_extend:SI (match_dup 6)))
6674 (set (match_operand:SI 0 "" "")
6675 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6676 "TARGET_ARM"
6677 "
6678 {
6679 rtx mem1, mem2;
6680 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6681
6682 mem1 = change_address (operands[1], QImode, addr);
6683 mem2 = change_address (operands[1], QImode,
6684 plus_constant (Pmode, addr, 1));
6685 operands[0] = gen_lowpart (SImode, operands[0]);
6686 operands[1] = mem1;
6687 operands[2] = gen_reg_rtx (SImode);
6688 operands[3] = gen_reg_rtx (SImode);
6689 operands[6] = mem2;
6690
6691 if (BYTES_BIG_ENDIAN)
6692 {
6693 operands[4] = operands[2];
6694 operands[5] = operands[3];
6695 }
6696 else
6697 {
6698 operands[4] = operands[3];
6699 operands[5] = operands[2];
6700 }
6701 }"
6702 )
6703
6704 (define_expand "movhi_bigend"
6705 [(set (match_dup 2)
6706 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6707 (const_int 16)))
6708 (set (match_dup 3)
6709 (ashiftrt:SI (match_dup 2) (const_int 16)))
6710 (set (match_operand:HI 0 "s_register_operand" "")
6711 (match_dup 4))]
6712 "TARGET_ARM"
6713 "
6714 operands[2] = gen_reg_rtx (SImode);
6715 operands[3] = gen_reg_rtx (SImode);
6716 operands[4] = gen_lowpart (HImode, operands[3]);
6717 "
6718 )
6719
6720 ;; Pattern to recognize insn generated default case above
6721 (define_insn "*movhi_insn_arch4"
6722 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6723 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
6724 "TARGET_ARM
6725 && arm_arch4 && !TARGET_HARD_FLOAT
6726 && (register_operand (operands[0], HImode)
6727 || register_operand (operands[1], HImode))"
6728 "@
6729 mov%?\\t%0, %1\\t%@ movhi
6730 mvn%?\\t%0, #%B1\\t%@ movhi
6731 movw%?\\t%0, %L1\\t%@ movhi
6732 strh%?\\t%1, %0\\t%@ movhi
6733 ldrh%?\\t%0, %1\\t%@ movhi"
6734 [(set_attr "predicable" "yes")
6735 (set_attr "pool_range" "*,*,*,*,256")
6736 (set_attr "neg_pool_range" "*,*,*,*,244")
6737 (set_attr "arch" "*,*,v6t2,*,*")
6738 (set_attr_alternative "type"
6739 [(if_then_else (match_operand 1 "const_int_operand" "")
6740 (const_string "mov_imm" )
6741 (const_string "mov_reg"))
6742 (const_string "mvn_imm")
6743 (const_string "mov_imm")
6744 (const_string "store1")
6745 (const_string "load1")])]
6746 )
6747
6748 (define_insn "*movhi_bytes"
6749 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
6750 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
6751 "TARGET_ARM && !TARGET_HARD_FLOAT"
6752 "@
6753 mov%?\\t%0, %1\\t%@ movhi
6754 mov%?\\t%0, %1\\t%@ movhi
6755 mvn%?\\t%0, #%B1\\t%@ movhi"
6756 [(set_attr "predicable" "yes")
6757 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
6758 )
6759
6760 ;; We use a DImode scratch because we may occasionally need an additional
6761 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
6762 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
6763 (define_expand "reload_outhi"
6764 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6765 (match_operand:HI 1 "s_register_operand" "r")
6766 (match_operand:DI 2 "s_register_operand" "=&l")])]
6767 "TARGET_EITHER"
6768 "if (TARGET_ARM)
6769 arm_reload_out_hi (operands);
6770 else
6771 thumb_reload_out_hi (operands);
6772 DONE;
6773 "
6774 )
6775
6776 (define_expand "reload_inhi"
6777 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6778 (match_operand:HI 1 "arm_reload_memory_operand" "o")
6779 (match_operand:DI 2 "s_register_operand" "=&r")])]
6780 "TARGET_EITHER"
6781 "
6782 if (TARGET_ARM)
6783 arm_reload_in_hi (operands);
6784 else
6785 thumb_reload_out_hi (operands);
6786 DONE;
6787 ")
6788
6789 (define_expand "movqi"
6790 [(set (match_operand:QI 0 "general_operand" "")
6791 (match_operand:QI 1 "general_operand" ""))]
6792 "TARGET_EITHER"
6793 "
6794 /* Everything except mem = const or mem = mem can be done easily */
6795
6796 if (can_create_pseudo_p ())
6797 {
6798 if (CONST_INT_P (operands[1]))
6799 {
6800 rtx reg = gen_reg_rtx (SImode);
6801
6802 /* For thumb we want an unsigned immediate, then we are more likely
6803 to be able to use a movs insn. */
6804 if (TARGET_THUMB)
6805 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6806
6807 emit_insn (gen_movsi (reg, operands[1]));
6808 operands[1] = gen_lowpart (QImode, reg);
6809 }
6810
6811 if (TARGET_THUMB)
6812 {
6813 /* ??? We shouldn't really get invalid addresses here, but this can
6814 happen if we are passed a SP (never OK for HImode/QImode) or
6815 virtual register (also rejected as illegitimate for HImode/QImode)
6816 relative address. */
6817 /* ??? This should perhaps be fixed elsewhere, for instance, in
6818 fixup_stack_1, by checking for other kinds of invalid addresses,
6819 e.g. a bare reference to a virtual register. This may confuse the
6820 alpha though, which must handle this case differently. */
6821 if (MEM_P (operands[0])
6822 && !memory_address_p (GET_MODE (operands[0]),
6823 XEXP (operands[0], 0)))
6824 operands[0]
6825 = replace_equiv_address (operands[0],
6826 copy_to_reg (XEXP (operands[0], 0)));
6827 if (MEM_P (operands[1])
6828 && !memory_address_p (GET_MODE (operands[1]),
6829 XEXP (operands[1], 0)))
6830 operands[1]
6831 = replace_equiv_address (operands[1],
6832 copy_to_reg (XEXP (operands[1], 0)));
6833 }
6834
6835 if (MEM_P (operands[1]) && optimize > 0)
6836 {
6837 rtx reg = gen_reg_rtx (SImode);
6838
6839 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6840 operands[1] = gen_lowpart (QImode, reg);
6841 }
6842
6843 if (MEM_P (operands[0]))
6844 operands[1] = force_reg (QImode, operands[1]);
6845 }
6846 else if (TARGET_THUMB
6847 && CONST_INT_P (operands[1])
6848 && !satisfies_constraint_I (operands[1]))
6849 {
6850 /* Handle loading a large integer during reload. */
6851
6852 /* Writing a constant to memory needs a scratch, which should
6853 be handled with SECONDARY_RELOADs. */
6854 gcc_assert (REG_P (operands[0]));
6855
6856 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6857 emit_insn (gen_movsi (operands[0], operands[1]));
6858 DONE;
6859 }
6860 "
6861 )
6862
6863 (define_insn "*arm_movqi_insn"
6864 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
6865 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
6866 "TARGET_32BIT
6867 && ( register_operand (operands[0], QImode)
6868 || register_operand (operands[1], QImode))"
6869 "@
6870 mov%?\\t%0, %1
6871 mov%?\\t%0, %1
6872 mov%?\\t%0, %1
6873 mov%?\\t%0, %1
6874 mvn%?\\t%0, #%B1
6875 ldrb%?\\t%0, %1
6876 strb%?\\t%1, %0
6877 ldrb%?\\t%0, %1
6878 strb%?\\t%1, %0"
6879 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
6880 (set_attr "predicable" "yes")
6881 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
6882 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6883 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
6884 )
6885
6886 ;; HFmode moves
6887 (define_expand "movhf"
6888 [(set (match_operand:HF 0 "general_operand" "")
6889 (match_operand:HF 1 "general_operand" ""))]
6890 "TARGET_EITHER"
6891 "
6892 if (TARGET_32BIT)
6893 {
6894 if (MEM_P (operands[0]))
6895 operands[1] = force_reg (HFmode, operands[1]);
6896 }
6897 else /* TARGET_THUMB1 */
6898 {
6899 if (can_create_pseudo_p ())
6900 {
6901 if (!REG_P (operands[0]))
6902 operands[1] = force_reg (HFmode, operands[1]);
6903 }
6904 }
6905 "
6906 )
6907
6908 (define_insn "*arm32_movhf"
6909 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6910 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6911 "TARGET_32BIT && !TARGET_HARD_FLOAT
6912 && ( s_register_operand (operands[0], HFmode)
6913 || s_register_operand (operands[1], HFmode))"
6914 "*
6915 switch (which_alternative)
6916 {
6917 case 0: /* ARM register from memory */
6918 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
6919 case 1: /* memory from ARM register */
6920 return \"strh%?\\t%1, %0\\t%@ __fp16\";
6921 case 2: /* ARM register from ARM register */
6922 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6923 case 3: /* ARM register from constant */
6924 {
6925 long bits;
6926 rtx ops[4];
6927
6928 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6929 HFmode);
6930 ops[0] = operands[0];
6931 ops[1] = GEN_INT (bits);
6932 ops[2] = GEN_INT (bits & 0xff00);
6933 ops[3] = GEN_INT (bits & 0x00ff);
6934
6935 if (arm_arch_thumb2)
6936 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6937 else
6938 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6939 return \"\";
6940 }
6941 default:
6942 gcc_unreachable ();
6943 }
6944 "
6945 [(set_attr "conds" "unconditional")
6946 (set_attr "type" "load1,store1,mov_reg,multiple")
6947 (set_attr "length" "4,4,4,8")
6948 (set_attr "predicable" "yes")
6949 (set_attr "predicable_short_it" "no")]
6950 )
6951
6952 (define_expand "movsf"
6953 [(set (match_operand:SF 0 "general_operand" "")
6954 (match_operand:SF 1 "general_operand" ""))]
6955 "TARGET_EITHER"
6956 "
6957 if (TARGET_32BIT)
6958 {
6959 if (MEM_P (operands[0]))
6960 operands[1] = force_reg (SFmode, operands[1]);
6961 }
6962 else /* TARGET_THUMB1 */
6963 {
6964 if (can_create_pseudo_p ())
6965 {
6966 if (!REG_P (operands[0]))
6967 operands[1] = force_reg (SFmode, operands[1]);
6968 }
6969 }
6970 "
6971 )
6972
6973 ;; Transform a floating-point move of a constant into a core register into
6974 ;; an SImode operation.
6975 (define_split
6976 [(set (match_operand:SF 0 "arm_general_register_operand" "")
6977 (match_operand:SF 1 "immediate_operand" ""))]
6978 "TARGET_EITHER
6979 && reload_completed
6980 && CONST_DOUBLE_P (operands[1])"
6981 [(set (match_dup 2) (match_dup 3))]
6982 "
6983 operands[2] = gen_lowpart (SImode, operands[0]);
6984 operands[3] = gen_lowpart (SImode, operands[1]);
6985 if (operands[2] == 0 || operands[3] == 0)
6986 FAIL;
6987 "
6988 )
6989
6990 (define_insn "*arm_movsf_soft_insn"
6991 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6992 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6993 "TARGET_32BIT
6994 && TARGET_SOFT_FLOAT
6995 && (!MEM_P (operands[0])
6996 || register_operand (operands[1], SFmode))"
6997 "@
6998 mov%?\\t%0, %1
6999 ldr%?\\t%0, %1\\t%@ float
7000 str%?\\t%1, %0\\t%@ float"
7001 [(set_attr "predicable" "yes")
7002 (set_attr "predicable_short_it" "no")
7003 (set_attr "type" "mov_reg,load1,store1")
7004 (set_attr "arm_pool_range" "*,4096,*")
7005 (set_attr "thumb2_pool_range" "*,4094,*")
7006 (set_attr "arm_neg_pool_range" "*,4084,*")
7007 (set_attr "thumb2_neg_pool_range" "*,0,*")]
7008 )
7009
7010 (define_expand "movdf"
7011 [(set (match_operand:DF 0 "general_operand" "")
7012 (match_operand:DF 1 "general_operand" ""))]
7013 "TARGET_EITHER"
7014 "
7015 if (TARGET_32BIT)
7016 {
7017 if (MEM_P (operands[0]))
7018 operands[1] = force_reg (DFmode, operands[1]);
7019 }
7020 else /* TARGET_THUMB */
7021 {
7022 if (can_create_pseudo_p ())
7023 {
7024 if (!REG_P (operands[0]))
7025 operands[1] = force_reg (DFmode, operands[1]);
7026 }
7027 }
7028 "
7029 )
7030
7031 ;; Reloading a df mode value stored in integer regs to memory can require a
7032 ;; scratch reg.
7033 (define_expand "reload_outdf"
7034 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
7035 (match_operand:DF 1 "s_register_operand" "r")
7036 (match_operand:SI 2 "s_register_operand" "=&r")]
7037 "TARGET_THUMB2"
7038 "
7039 {
7040 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
7041
7042 if (code == REG)
7043 operands[2] = XEXP (operands[0], 0);
7044 else if (code == POST_INC || code == PRE_DEC)
7045 {
7046 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
7047 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
7048 emit_insn (gen_movdi (operands[0], operands[1]));
7049 DONE;
7050 }
7051 else if (code == PRE_INC)
7052 {
7053 rtx reg = XEXP (XEXP (operands[0], 0), 0);
7054
7055 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
7056 operands[2] = reg;
7057 }
7058 else if (code == POST_DEC)
7059 operands[2] = XEXP (XEXP (operands[0], 0), 0);
7060 else
7061 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
7062 XEXP (XEXP (operands[0], 0), 1)));
7063
7064 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
7065 operands[1]));
7066
7067 if (code == POST_DEC)
7068 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
7069
7070 DONE;
7071 }"
7072 )
7073
7074 (define_insn "*movdf_soft_insn"
7075 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
7076 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
7077 "TARGET_32BIT && TARGET_SOFT_FLOAT
7078 && ( register_operand (operands[0], DFmode)
7079 || register_operand (operands[1], DFmode))"
7080 "*
7081 switch (which_alternative)
7082 {
7083 case 0:
7084 case 1:
7085 case 2:
7086 return \"#\";
7087 default:
7088 return output_move_double (operands, true, NULL);
7089 }
7090 "
7091 [(set_attr "length" "8,12,16,8,8")
7092 (set_attr "type" "multiple,multiple,multiple,load2,store2")
7093 (set_attr "arm_pool_range" "*,*,*,1020,*")
7094 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
7095 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
7096 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
7097 )
7098 \f
7099
7100 ;; load- and store-multiple insns
7101 ;; The arm can load/store any set of registers, provided that they are in
7102 ;; ascending order, but these expanders assume a contiguous set.
7103
7104 (define_expand "load_multiple"
7105 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7106 (match_operand:SI 1 "" ""))
7107 (use (match_operand:SI 2 "" ""))])]
7108 "TARGET_32BIT"
7109 {
7110 HOST_WIDE_INT offset = 0;
7111
7112 /* Support only fixed point registers. */
7113 if (!CONST_INT_P (operands[2])
7114 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
7115 || INTVAL (operands[2]) < 2
7116 || !MEM_P (operands[1])
7117 || !REG_P (operands[0])
7118 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
7119 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
7120 FAIL;
7121
7122 operands[3]
7123 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
7124 INTVAL (operands[2]),
7125 force_reg (SImode, XEXP (operands[1], 0)),
7126 FALSE, operands[1], &offset);
7127 })
7128
7129 (define_expand "store_multiple"
7130 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
7131 (match_operand:SI 1 "" ""))
7132 (use (match_operand:SI 2 "" ""))])]
7133 "TARGET_32BIT"
7134 {
7135 HOST_WIDE_INT offset = 0;
7136
7137 /* Support only fixed point registers. */
7138 if (!CONST_INT_P (operands[2])
7139 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
7140 || INTVAL (operands[2]) < 2
7141 || !REG_P (operands[1])
7142 || !MEM_P (operands[0])
7143 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
7144 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
7145 FAIL;
7146
7147 operands[3]
7148 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
7149 INTVAL (operands[2]),
7150 force_reg (SImode, XEXP (operands[0], 0)),
7151 FALSE, operands[0], &offset);
7152 })
7153
7154
7155 (define_expand "setmemsi"
7156 [(match_operand:BLK 0 "general_operand" "")
7157 (match_operand:SI 1 "const_int_operand" "")
7158 (match_operand:SI 2 "const_int_operand" "")
7159 (match_operand:SI 3 "const_int_operand" "")]
7160 "TARGET_32BIT"
7161 {
7162 if (arm_gen_setmem (operands))
7163 DONE;
7164
7165 FAIL;
7166 })
7167
7168
7169 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
7170 ;; We could let this apply for blocks of less than this, but it clobbers so
7171 ;; many registers that there is then probably a better way.
7172
7173 (define_expand "movmemqi"
7174 [(match_operand:BLK 0 "general_operand" "")
7175 (match_operand:BLK 1 "general_operand" "")
7176 (match_operand:SI 2 "const_int_operand" "")
7177 (match_operand:SI 3 "const_int_operand" "")]
7178 ""
7179 "
7180 if (TARGET_32BIT)
7181 {
7182 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
7183 && !optimize_function_for_size_p (cfun))
7184 {
7185 if (gen_movmem_ldrd_strd (operands))
7186 DONE;
7187 FAIL;
7188 }
7189
7190 if (arm_gen_movmemqi (operands))
7191 DONE;
7192 FAIL;
7193 }
7194 else /* TARGET_THUMB1 */
7195 {
7196 if ( INTVAL (operands[3]) != 4
7197 || INTVAL (operands[2]) > 48)
7198 FAIL;
7199
7200 thumb_expand_movmemqi (operands);
7201 DONE;
7202 }
7203 "
7204 )
7205 \f
7206
7207 ;; Compare & branch insns
7208 ;; The range calculations are based as follows:
7209 ;; For forward branches, the address calculation returns the address of
7210 ;; the next instruction. This is 2 beyond the branch instruction.
7211 ;; For backward branches, the address calculation returns the address of
7212 ;; the first instruction in this pattern (cmp). This is 2 before the branch
7213 ;; instruction for the shortest sequence, and 4 before the branch instruction
7214 ;; if we have to jump around an unconditional branch.
7215 ;; To the basic branch range the PC offset must be added (this is +4).
7216 ;; So for forward branches we have
7217 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
7218 ;; And for backward branches we have
7219 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
7220 ;;
7221 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
7222 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
7223
7224 (define_expand "cbranchsi4"
7225 [(set (pc) (if_then_else
7226 (match_operator 0 "expandable_comparison_operator"
7227 [(match_operand:SI 1 "s_register_operand" "")
7228 (match_operand:SI 2 "nonmemory_operand" "")])
7229 (label_ref (match_operand 3 "" ""))
7230 (pc)))]
7231 "TARGET_EITHER"
7232 "
7233 if (!TARGET_THUMB1)
7234 {
7235 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7236 FAIL;
7237 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7238 operands[3]));
7239 DONE;
7240 }
7241 if (thumb1_cmpneg_operand (operands[2], SImode))
7242 {
7243 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
7244 operands[3], operands[0]));
7245 DONE;
7246 }
7247 if (!thumb1_cmp_operand (operands[2], SImode))
7248 operands[2] = force_reg (SImode, operands[2]);
7249 ")
7250
7251 (define_expand "cbranchsf4"
7252 [(set (pc) (if_then_else
7253 (match_operator 0 "expandable_comparison_operator"
7254 [(match_operand:SF 1 "s_register_operand" "")
7255 (match_operand:SF 2 "vfp_compare_operand" "")])
7256 (label_ref (match_operand 3 "" ""))
7257 (pc)))]
7258 "TARGET_32BIT && TARGET_HARD_FLOAT"
7259 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7260 operands[3])); DONE;"
7261 )
7262
7263 (define_expand "cbranchdf4"
7264 [(set (pc) (if_then_else
7265 (match_operator 0 "expandable_comparison_operator"
7266 [(match_operand:DF 1 "s_register_operand" "")
7267 (match_operand:DF 2 "vfp_compare_operand" "")])
7268 (label_ref (match_operand 3 "" ""))
7269 (pc)))]
7270 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7271 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7272 operands[3])); DONE;"
7273 )
7274
7275 (define_expand "cbranchdi4"
7276 [(set (pc) (if_then_else
7277 (match_operator 0 "expandable_comparison_operator"
7278 [(match_operand:DI 1 "s_register_operand" "")
7279 (match_operand:DI 2 "cmpdi_operand" "")])
7280 (label_ref (match_operand 3 "" ""))
7281 (pc)))]
7282 "TARGET_32BIT"
7283 "{
7284 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
7285 FAIL;
7286 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
7287 operands[3]));
7288 DONE;
7289 }"
7290 )
7291
7292 ;; Comparison and test insns
7293
7294 (define_insn "*arm_cmpsi_insn"
7295 [(set (reg:CC CC_REGNUM)
7296 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
7297 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
7298 "TARGET_32BIT"
7299 "@
7300 cmp%?\\t%0, %1
7301 cmp%?\\t%0, %1
7302 cmp%?\\t%0, %1
7303 cmp%?\\t%0, %1
7304 cmn%?\\t%0, #%n1"
7305 [(set_attr "conds" "set")
7306 (set_attr "arch" "t2,t2,any,any,any")
7307 (set_attr "length" "2,2,4,4,4")
7308 (set_attr "predicable" "yes")
7309 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
7310 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
7311 )
7312
7313 (define_insn "*cmpsi_shiftsi"
7314 [(set (reg:CC CC_REGNUM)
7315 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
7316 (match_operator:SI 3 "shift_operator"
7317 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7318 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
7319 "TARGET_32BIT"
7320 "cmp\\t%0, %1%S3"
7321 [(set_attr "conds" "set")
7322 (set_attr "shift" "1")
7323 (set_attr "arch" "32,a,a")
7324 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
7325
7326 (define_insn "*cmpsi_shiftsi_swp"
7327 [(set (reg:CC_SWP CC_REGNUM)
7328 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7329 [(match_operand:SI 1 "s_register_operand" "r,r,r")
7330 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
7331 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
7332 "TARGET_32BIT"
7333 "cmp%?\\t%0, %1%S3"
7334 [(set_attr "conds" "set")
7335 (set_attr "shift" "1")
7336 (set_attr "arch" "32,a,a")
7337 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
7338
7339 (define_insn "*arm_cmpsi_negshiftsi_si"
7340 [(set (reg:CC_Z CC_REGNUM)
7341 (compare:CC_Z
7342 (neg:SI (match_operator:SI 1 "shift_operator"
7343 [(match_operand:SI 2 "s_register_operand" "r")
7344 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7345 (match_operand:SI 0 "s_register_operand" "r")))]
7346 "TARGET_ARM"
7347 "cmn%?\\t%0, %2%S1"
7348 [(set_attr "conds" "set")
7349 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7350 (const_string "alus_shift_imm")
7351 (const_string "alus_shift_reg")))
7352 (set_attr "predicable" "yes")]
7353 )
7354
7355 ;; DImode comparisons. The generic code generates branches that
7356 ;; if-conversion can not reduce to a conditional compare, so we do
7357 ;; that directly.
7358
7359 (define_insn_and_split "*arm_cmpdi_insn"
7360 [(set (reg:CC_NCV CC_REGNUM)
7361 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7362 (match_operand:DI 1 "arm_di_operand" "rDi")))
7363 (clobber (match_scratch:SI 2 "=r"))]
7364 "TARGET_32BIT"
7365 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7366 "&& reload_completed"
7367 [(set (reg:CC CC_REGNUM)
7368 (compare:CC (match_dup 0) (match_dup 1)))
7369 (parallel [(set (reg:CC CC_REGNUM)
7370 (compare:CC (match_dup 3) (match_dup 4)))
7371 (set (match_dup 2)
7372 (minus:SI (match_dup 5)
7373 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7374 {
7375 operands[3] = gen_highpart (SImode, operands[0]);
7376 operands[0] = gen_lowpart (SImode, operands[0]);
7377 if (CONST_INT_P (operands[1]))
7378 {
7379 operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7380 DImode,
7381 operands[1])));
7382 operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7383 }
7384 else
7385 {
7386 operands[4] = gen_highpart (SImode, operands[1]);
7387 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7388 }
7389 operands[1] = gen_lowpart (SImode, operands[1]);
7390 operands[2] = gen_lowpart (SImode, operands[2]);
7391 }
7392 [(set_attr "conds" "set")
7393 (set_attr "length" "8")
7394 (set_attr "type" "multiple")]
7395 )
7396
7397 (define_insn_and_split "*arm_cmpdi_unsigned"
7398 [(set (reg:CC_CZ CC_REGNUM)
7399 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7400 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7401
7402 "TARGET_32BIT"
7403 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7404 "&& reload_completed"
7405 [(set (reg:CC CC_REGNUM)
7406 (compare:CC (match_dup 2) (match_dup 3)))
7407 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7408 (set (reg:CC CC_REGNUM)
7409 (compare:CC (match_dup 0) (match_dup 1))))]
7410 {
7411 operands[2] = gen_highpart (SImode, operands[0]);
7412 operands[0] = gen_lowpart (SImode, operands[0]);
7413 if (CONST_INT_P (operands[1]))
7414 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7415 else
7416 operands[3] = gen_highpart (SImode, operands[1]);
7417 operands[1] = gen_lowpart (SImode, operands[1]);
7418 }
7419 [(set_attr "conds" "set")
7420 (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7421 (set_attr "arch" "t2,t2,t2,a")
7422 (set_attr "length" "6,6,10,8")
7423 (set_attr "type" "multiple")]
7424 )
7425
7426 (define_insn "*arm_cmpdi_zero"
7427 [(set (reg:CC_Z CC_REGNUM)
7428 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7429 (const_int 0)))
7430 (clobber (match_scratch:SI 1 "=r"))]
7431 "TARGET_32BIT"
7432 "orrs%?\\t%1, %Q0, %R0"
7433 [(set_attr "conds" "set")
7434 (set_attr "type" "logics_reg")]
7435 )
7436
7437 ; This insn allows redundant compares to be removed by cse, nothing should
7438 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7439 ; is deleted later on. The match_dup will match the mode here, so that
7440 ; mode changes of the condition codes aren't lost by this even though we don't
7441 ; specify what they are.
7442
7443 (define_insn "*deleted_compare"
7444 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7445 "TARGET_32BIT"
7446 "\\t%@ deleted compare"
7447 [(set_attr "conds" "set")
7448 (set_attr "length" "0")
7449 (set_attr "type" "no_insn")]
7450 )
7451
7452 \f
7453 ;; Conditional branch insns
7454
7455 (define_expand "cbranch_cc"
7456 [(set (pc)
7457 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7458 (match_operand 2 "" "")])
7459 (label_ref (match_operand 3 "" ""))
7460 (pc)))]
7461 "TARGET_32BIT"
7462 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7463 operands[1], operands[2], NULL_RTX);
7464 operands[2] = const0_rtx;"
7465 )
7466
7467 ;;
7468 ;; Patterns to match conditional branch insns.
7469 ;;
7470
7471 (define_insn "arm_cond_branch"
7472 [(set (pc)
7473 (if_then_else (match_operator 1 "arm_comparison_operator"
7474 [(match_operand 2 "cc_register" "") (const_int 0)])
7475 (label_ref (match_operand 0 "" ""))
7476 (pc)))]
7477 "TARGET_32BIT"
7478 "*
7479 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7480 {
7481 arm_ccfsm_state += 2;
7482 return \"\";
7483 }
7484 return \"b%d1\\t%l0\";
7485 "
7486 [(set_attr "conds" "use")
7487 (set_attr "type" "branch")
7488 (set (attr "length")
7489 (if_then_else
7490 (and (match_test "TARGET_THUMB2")
7491 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7492 (le (minus (match_dup 0) (pc)) (const_int 256))))
7493 (const_int 2)
7494 (const_int 4)))]
7495 )
7496
7497 (define_insn "*arm_cond_branch_reversed"
7498 [(set (pc)
7499 (if_then_else (match_operator 1 "arm_comparison_operator"
7500 [(match_operand 2 "cc_register" "") (const_int 0)])
7501 (pc)
7502 (label_ref (match_operand 0 "" ""))))]
7503 "TARGET_32BIT"
7504 "*
7505 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7506 {
7507 arm_ccfsm_state += 2;
7508 return \"\";
7509 }
7510 return \"b%D1\\t%l0\";
7511 "
7512 [(set_attr "conds" "use")
7513 (set_attr "type" "branch")
7514 (set (attr "length")
7515 (if_then_else
7516 (and (match_test "TARGET_THUMB2")
7517 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7518 (le (minus (match_dup 0) (pc)) (const_int 256))))
7519 (const_int 2)
7520 (const_int 4)))]
7521 )
7522
7523 \f
7524
7525 ; scc insns
7526
7527 (define_expand "cstore_cc"
7528 [(set (match_operand:SI 0 "s_register_operand" "")
7529 (match_operator:SI 1 "" [(match_operand 2 "" "")
7530 (match_operand 3 "" "")]))]
7531 "TARGET_32BIT"
7532 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7533 operands[2], operands[3], NULL_RTX);
7534 operands[3] = const0_rtx;"
7535 )
7536
7537 (define_insn_and_split "*mov_scc"
7538 [(set (match_operand:SI 0 "s_register_operand" "=r")
7539 (match_operator:SI 1 "arm_comparison_operator_mode"
7540 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7541 "TARGET_ARM"
7542 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7543 "TARGET_ARM"
7544 [(set (match_dup 0)
7545 (if_then_else:SI (match_dup 1)
7546 (const_int 1)
7547 (const_int 0)))]
7548 ""
7549 [(set_attr "conds" "use")
7550 (set_attr "length" "8")
7551 (set_attr "type" "multiple")]
7552 )
7553
7554 (define_insn_and_split "*mov_negscc"
7555 [(set (match_operand:SI 0 "s_register_operand" "=r")
7556 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
7557 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7558 "TARGET_ARM"
7559 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7560 "TARGET_ARM"
7561 [(set (match_dup 0)
7562 (if_then_else:SI (match_dup 1)
7563 (match_dup 3)
7564 (const_int 0)))]
7565 {
7566 operands[3] = GEN_INT (~0);
7567 }
7568 [(set_attr "conds" "use")
7569 (set_attr "length" "8")
7570 (set_attr "type" "multiple")]
7571 )
7572
7573 (define_insn_and_split "*mov_notscc"
7574 [(set (match_operand:SI 0 "s_register_operand" "=r")
7575 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7576 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7577 "TARGET_ARM"
7578 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7579 "TARGET_ARM"
7580 [(set (match_dup 0)
7581 (if_then_else:SI (match_dup 1)
7582 (match_dup 3)
7583 (match_dup 4)))]
7584 {
7585 operands[3] = GEN_INT (~1);
7586 operands[4] = GEN_INT (~0);
7587 }
7588 [(set_attr "conds" "use")
7589 (set_attr "length" "8")
7590 (set_attr "type" "multiple")]
7591 )
7592
7593 (define_expand "cstoresi4"
7594 [(set (match_operand:SI 0 "s_register_operand" "")
7595 (match_operator:SI 1 "expandable_comparison_operator"
7596 [(match_operand:SI 2 "s_register_operand" "")
7597 (match_operand:SI 3 "reg_or_int_operand" "")]))]
7598 "TARGET_32BIT || TARGET_THUMB1"
7599 "{
7600 rtx op3, scratch, scratch2;
7601
7602 if (!TARGET_THUMB1)
7603 {
7604 if (!arm_add_operand (operands[3], SImode))
7605 operands[3] = force_reg (SImode, operands[3]);
7606 emit_insn (gen_cstore_cc (operands[0], operands[1],
7607 operands[2], operands[3]));
7608 DONE;
7609 }
7610
7611 if (operands[3] == const0_rtx)
7612 {
7613 switch (GET_CODE (operands[1]))
7614 {
7615 case EQ:
7616 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7617 break;
7618
7619 case NE:
7620 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7621 break;
7622
7623 case LE:
7624 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7625 NULL_RTX, 0, OPTAB_WIDEN);
7626 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7627 NULL_RTX, 0, OPTAB_WIDEN);
7628 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7629 operands[0], 1, OPTAB_WIDEN);
7630 break;
7631
7632 case GE:
7633 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7634 NULL_RTX, 1);
7635 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7636 NULL_RTX, 1, OPTAB_WIDEN);
7637 break;
7638
7639 case GT:
7640 scratch = expand_binop (SImode, ashr_optab, operands[2],
7641 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7642 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7643 NULL_RTX, 0, OPTAB_WIDEN);
7644 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7645 0, OPTAB_WIDEN);
7646 break;
7647
7648 /* LT is handled by generic code. No need for unsigned with 0. */
7649 default:
7650 FAIL;
7651 }
7652 DONE;
7653 }
7654
7655 switch (GET_CODE (operands[1]))
7656 {
7657 case EQ:
7658 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7659 NULL_RTX, 0, OPTAB_WIDEN);
7660 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7661 break;
7662
7663 case NE:
7664 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7665 NULL_RTX, 0, OPTAB_WIDEN);
7666 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7667 break;
7668
7669 case LE:
7670 op3 = force_reg (SImode, operands[3]);
7671
7672 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7673 NULL_RTX, 1, OPTAB_WIDEN);
7674 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7675 NULL_RTX, 0, OPTAB_WIDEN);
7676 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7677 op3, operands[2]));
7678 break;
7679
7680 case GE:
7681 op3 = operands[3];
7682 if (!thumb1_cmp_operand (op3, SImode))
7683 op3 = force_reg (SImode, op3);
7684 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7685 NULL_RTX, 0, OPTAB_WIDEN);
7686 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7687 NULL_RTX, 1, OPTAB_WIDEN);
7688 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7689 operands[2], op3));
7690 break;
7691
7692 case LEU:
7693 op3 = force_reg (SImode, operands[3]);
7694 scratch = force_reg (SImode, const0_rtx);
7695 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7696 op3, operands[2]));
7697 break;
7698
7699 case GEU:
7700 op3 = operands[3];
7701 if (!thumb1_cmp_operand (op3, SImode))
7702 op3 = force_reg (SImode, op3);
7703 scratch = force_reg (SImode, const0_rtx);
7704 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7705 operands[2], op3));
7706 break;
7707
7708 case LTU:
7709 op3 = operands[3];
7710 if (!thumb1_cmp_operand (op3, SImode))
7711 op3 = force_reg (SImode, op3);
7712 scratch = gen_reg_rtx (SImode);
7713 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7714 break;
7715
7716 case GTU:
7717 op3 = force_reg (SImode, operands[3]);
7718 scratch = gen_reg_rtx (SImode);
7719 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7720 break;
7721
7722 /* No good sequences for GT, LT. */
7723 default:
7724 FAIL;
7725 }
7726 DONE;
7727 }")
7728
7729 (define_expand "cstorehf4"
7730 [(set (match_operand:SI 0 "s_register_operand")
7731 (match_operator:SI 1 "expandable_comparison_operator"
7732 [(match_operand:HF 2 "s_register_operand")
7733 (match_operand:HF 3 "vfp_compare_operand")]))]
7734 "TARGET_VFP_FP16INST"
7735 {
7736 if (!arm_validize_comparison (&operands[1],
7737 &operands[2],
7738 &operands[3]))
7739 FAIL;
7740
7741 emit_insn (gen_cstore_cc (operands[0], operands[1],
7742 operands[2], operands[3]));
7743 DONE;
7744 }
7745 )
7746
7747 (define_expand "cstoresf4"
7748 [(set (match_operand:SI 0 "s_register_operand" "")
7749 (match_operator:SI 1 "expandable_comparison_operator"
7750 [(match_operand:SF 2 "s_register_operand" "")
7751 (match_operand:SF 3 "vfp_compare_operand" "")]))]
7752 "TARGET_32BIT && TARGET_HARD_FLOAT"
7753 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7754 operands[2], operands[3])); DONE;"
7755 )
7756
7757 (define_expand "cstoredf4"
7758 [(set (match_operand:SI 0 "s_register_operand" "")
7759 (match_operator:SI 1 "expandable_comparison_operator"
7760 [(match_operand:DF 2 "s_register_operand" "")
7761 (match_operand:DF 3 "vfp_compare_operand" "")]))]
7762 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7763 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7764 operands[2], operands[3])); DONE;"
7765 )
7766
7767 (define_expand "cstoredi4"
7768 [(set (match_operand:SI 0 "s_register_operand" "")
7769 (match_operator:SI 1 "expandable_comparison_operator"
7770 [(match_operand:DI 2 "s_register_operand" "")
7771 (match_operand:DI 3 "cmpdi_operand" "")]))]
7772 "TARGET_32BIT"
7773 "{
7774 if (!arm_validize_comparison (&operands[1],
7775 &operands[2],
7776 &operands[3]))
7777 FAIL;
7778 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7779 operands[3]));
7780 DONE;
7781 }"
7782 )
7783
7784 \f
7785 ;; Conditional move insns
7786
7787 (define_expand "movsicc"
7788 [(set (match_operand:SI 0 "s_register_operand" "")
7789 (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
7790 (match_operand:SI 2 "arm_not_operand" "")
7791 (match_operand:SI 3 "arm_not_operand" "")))]
7792 "TARGET_32BIT"
7793 "
7794 {
7795 enum rtx_code code;
7796 rtx ccreg;
7797
7798 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7799 &XEXP (operands[1], 1)))
7800 FAIL;
7801
7802 code = GET_CODE (operands[1]);
7803 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7804 XEXP (operands[1], 1), NULL_RTX);
7805 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7806 }"
7807 )
7808
7809 (define_expand "movhfcc"
7810 [(set (match_operand:HF 0 "s_register_operand")
7811 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7812 (match_operand:HF 2 "s_register_operand")
7813 (match_operand:HF 3 "s_register_operand")))]
7814 "TARGET_VFP_FP16INST"
7815 "
7816 {
7817 enum rtx_code code = GET_CODE (operands[1]);
7818 rtx ccreg;
7819
7820 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7821 &XEXP (operands[1], 1)))
7822 FAIL;
7823
7824 code = GET_CODE (operands[1]);
7825 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7826 XEXP (operands[1], 1), NULL_RTX);
7827 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7828 }"
7829 )
7830
7831 (define_expand "movsfcc"
7832 [(set (match_operand:SF 0 "s_register_operand" "")
7833 (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
7834 (match_operand:SF 2 "s_register_operand" "")
7835 (match_operand:SF 3 "s_register_operand" "")))]
7836 "TARGET_32BIT && TARGET_HARD_FLOAT"
7837 "
7838 {
7839 enum rtx_code code = GET_CODE (operands[1]);
7840 rtx ccreg;
7841
7842 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7843 &XEXP (operands[1], 1)))
7844 FAIL;
7845
7846 code = GET_CODE (operands[1]);
7847 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7848 XEXP (operands[1], 1), NULL_RTX);
7849 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7850 }"
7851 )
7852
7853 (define_expand "movdfcc"
7854 [(set (match_operand:DF 0 "s_register_operand" "")
7855 (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
7856 (match_operand:DF 2 "s_register_operand" "")
7857 (match_operand:DF 3 "s_register_operand" "")))]
7858 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7859 "
7860 {
7861 enum rtx_code code = GET_CODE (operands[1]);
7862 rtx ccreg;
7863
7864 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7865 &XEXP (operands[1], 1)))
7866 FAIL;
7867 code = GET_CODE (operands[1]);
7868 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7869 XEXP (operands[1], 1), NULL_RTX);
7870 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7871 }"
7872 )
7873
7874 (define_insn "*cmov<mode>"
7875 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7876 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7877 [(match_operand 2 "cc_register" "") (const_int 0)])
7878 (match_operand:SDF 3 "s_register_operand"
7879 "<F_constraint>")
7880 (match_operand:SDF 4 "s_register_operand"
7881 "<F_constraint>")))]
7882 "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7883 "*
7884 {
7885 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7886 switch (code)
7887 {
7888 case ARM_GE:
7889 case ARM_GT:
7890 case ARM_EQ:
7891 case ARM_VS:
7892 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7893 case ARM_LT:
7894 case ARM_LE:
7895 case ARM_NE:
7896 case ARM_VC:
7897 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7898 default:
7899 gcc_unreachable ();
7900 }
7901 return \"\";
7902 }"
7903 [(set_attr "conds" "use")
7904 (set_attr "type" "fcsel")]
7905 )
7906
7907 (define_insn "*cmovhf"
7908 [(set (match_operand:HF 0 "s_register_operand" "=t")
7909 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7910 [(match_operand 2 "cc_register" "") (const_int 0)])
7911 (match_operand:HF 3 "s_register_operand" "t")
7912 (match_operand:HF 4 "s_register_operand" "t")))]
7913 "TARGET_VFP_FP16INST"
7914 "*
7915 {
7916 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7917 switch (code)
7918 {
7919 case ARM_GE:
7920 case ARM_GT:
7921 case ARM_EQ:
7922 case ARM_VS:
7923 return \"vsel%d1.f16\\t%0, %3, %4\";
7924 case ARM_LT:
7925 case ARM_LE:
7926 case ARM_NE:
7927 case ARM_VC:
7928 return \"vsel%D1.f16\\t%0, %4, %3\";
7929 default:
7930 gcc_unreachable ();
7931 }
7932 return \"\";
7933 }"
7934 [(set_attr "conds" "use")
7935 (set_attr "type" "fcsel")]
7936 )
7937
7938 (define_insn_and_split "*movsicc_insn"
7939 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7940 (if_then_else:SI
7941 (match_operator 3 "arm_comparison_operator"
7942 [(match_operand 4 "cc_register" "") (const_int 0)])
7943 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7944 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7945 "TARGET_ARM"
7946 "@
7947 mov%D3\\t%0, %2
7948 mvn%D3\\t%0, #%B2
7949 mov%d3\\t%0, %1
7950 mvn%d3\\t%0, #%B1
7951 #
7952 #
7953 #
7954 #"
7955 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7956 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7957 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7958 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7959 "&& reload_completed"
7960 [(const_int 0)]
7961 {
7962 enum rtx_code rev_code;
7963 machine_mode mode;
7964 rtx rev_cond;
7965
7966 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7967 operands[3],
7968 gen_rtx_SET (operands[0], operands[1])));
7969
7970 rev_code = GET_CODE (operands[3]);
7971 mode = GET_MODE (operands[4]);
7972 if (mode == CCFPmode || mode == CCFPEmode)
7973 rev_code = reverse_condition_maybe_unordered (rev_code);
7974 else
7975 rev_code = reverse_condition (rev_code);
7976
7977 rev_cond = gen_rtx_fmt_ee (rev_code,
7978 VOIDmode,
7979 operands[4],
7980 const0_rtx);
7981 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7982 rev_cond,
7983 gen_rtx_SET (operands[0], operands[2])));
7984 DONE;
7985 }
7986 [(set_attr "length" "4,4,4,4,8,8,8,8")
7987 (set_attr "conds" "use")
7988 (set_attr_alternative "type"
7989 [(if_then_else (match_operand 2 "const_int_operand" "")
7990 (const_string "mov_imm")
7991 (const_string "mov_reg"))
7992 (const_string "mvn_imm")
7993 (if_then_else (match_operand 1 "const_int_operand" "")
7994 (const_string "mov_imm")
7995 (const_string "mov_reg"))
7996 (const_string "mvn_imm")
7997 (const_string "multiple")
7998 (const_string "multiple")
7999 (const_string "multiple")
8000 (const_string "multiple")])]
8001 )
8002
8003 (define_insn "*movsfcc_soft_insn"
8004 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8005 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8006 [(match_operand 4 "cc_register" "") (const_int 0)])
8007 (match_operand:SF 1 "s_register_operand" "0,r")
8008 (match_operand:SF 2 "s_register_operand" "r,0")))]
8009 "TARGET_ARM && TARGET_SOFT_FLOAT"
8010 "@
8011 mov%D3\\t%0, %2
8012 mov%d3\\t%0, %1"
8013 [(set_attr "conds" "use")
8014 (set_attr "type" "mov_reg")]
8015 )
8016
8017 \f
8018 ;; Jump and linkage insns
8019
8020 (define_expand "jump"
8021 [(set (pc)
8022 (label_ref (match_operand 0 "" "")))]
8023 "TARGET_EITHER"
8024 ""
8025 )
8026
8027 (define_insn "*arm_jump"
8028 [(set (pc)
8029 (label_ref (match_operand 0 "" "")))]
8030 "TARGET_32BIT"
8031 "*
8032 {
8033 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8034 {
8035 arm_ccfsm_state += 2;
8036 return \"\";
8037 }
8038 return \"b%?\\t%l0\";
8039 }
8040 "
8041 [(set_attr "predicable" "yes")
8042 (set (attr "length")
8043 (if_then_else
8044 (and (match_test "TARGET_THUMB2")
8045 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8046 (le (minus (match_dup 0) (pc)) (const_int 2048))))
8047 (const_int 2)
8048 (const_int 4)))
8049 (set_attr "type" "branch")]
8050 )
8051
8052 (define_expand "call"
8053 [(parallel [(call (match_operand 0 "memory_operand" "")
8054 (match_operand 1 "general_operand" ""))
8055 (use (match_operand 2 "" ""))
8056 (clobber (reg:SI LR_REGNUM))])]
8057 "TARGET_EITHER"
8058 "
8059 {
8060 rtx callee, pat;
8061 tree addr = MEM_EXPR (operands[0]);
8062
8063 /* In an untyped call, we can get NULL for operand 2. */
8064 if (operands[2] == NULL_RTX)
8065 operands[2] = const0_rtx;
8066
8067 /* Decide if we should generate indirect calls by loading the
8068 32-bit address of the callee into a register before performing the
8069 branch and link. */
8070 callee = XEXP (operands[0], 0);
8071 if (GET_CODE (callee) == SYMBOL_REF
8072 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8073 : !REG_P (callee))
8074 XEXP (operands[0], 0) = force_reg (Pmode, callee);
8075
8076 if (detect_cmse_nonsecure_call (addr))
8077 {
8078 pat = gen_nonsecure_call_internal (operands[0], operands[1],
8079 operands[2]);
8080 emit_call_insn (pat);
8081 }
8082 else
8083 {
8084 pat = gen_call_internal (operands[0], operands[1], operands[2]);
8085 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
8086 }
8087 DONE;
8088 }"
8089 )
8090
8091 (define_expand "call_internal"
8092 [(parallel [(call (match_operand 0 "memory_operand" "")
8093 (match_operand 1 "general_operand" ""))
8094 (use (match_operand 2 "" ""))
8095 (clobber (reg:SI LR_REGNUM))])])
8096
8097 (define_expand "nonsecure_call_internal"
8098 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
8099 UNSPEC_NONSECURE_MEM)
8100 (match_operand 1 "general_operand" ""))
8101 (use (match_operand 2 "" ""))
8102 (clobber (reg:SI LR_REGNUM))
8103 (clobber (reg:SI 4))])]
8104 "use_cmse"
8105 "
8106 {
8107 rtx tmp;
8108 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
8109 gen_rtx_REG (SImode, 4),
8110 SImode);
8111
8112 operands[0] = replace_equiv_address (operands[0], tmp);
8113 }")
8114
8115 (define_insn "*call_reg_armv5"
8116 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8117 (match_operand 1 "" ""))
8118 (use (match_operand 2 "" ""))
8119 (clobber (reg:SI LR_REGNUM))]
8120 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
8121 "blx%?\\t%0"
8122 [(set_attr "type" "call")]
8123 )
8124
8125 (define_insn "*call_reg_arm"
8126 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8127 (match_operand 1 "" ""))
8128 (use (match_operand 2 "" ""))
8129 (clobber (reg:SI LR_REGNUM))]
8130 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
8131 "*
8132 return output_call (operands);
8133 "
8134 ;; length is worst case, normally it is only two
8135 [(set_attr "length" "12")
8136 (set_attr "type" "call")]
8137 )
8138
8139
8140 (define_expand "call_value"
8141 [(parallel [(set (match_operand 0 "" "")
8142 (call (match_operand 1 "memory_operand" "")
8143 (match_operand 2 "general_operand" "")))
8144 (use (match_operand 3 "" ""))
8145 (clobber (reg:SI LR_REGNUM))])]
8146 "TARGET_EITHER"
8147 "
8148 {
8149 rtx pat, callee;
8150 tree addr = MEM_EXPR (operands[1]);
8151
8152 /* In an untyped call, we can get NULL for operand 2. */
8153 if (operands[3] == 0)
8154 operands[3] = const0_rtx;
8155
8156 /* Decide if we should generate indirect calls by loading the
8157 32-bit address of the callee into a register before performing the
8158 branch and link. */
8159 callee = XEXP (operands[1], 0);
8160 if (GET_CODE (callee) == SYMBOL_REF
8161 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8162 : !REG_P (callee))
8163 XEXP (operands[1], 0) = force_reg (Pmode, callee);
8164
8165 if (detect_cmse_nonsecure_call (addr))
8166 {
8167 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
8168 operands[2], operands[3]);
8169 emit_call_insn (pat);
8170 }
8171 else
8172 {
8173 pat = gen_call_value_internal (operands[0], operands[1],
8174 operands[2], operands[3]);
8175 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
8176 }
8177 DONE;
8178 }"
8179 )
8180
8181 (define_expand "call_value_internal"
8182 [(parallel [(set (match_operand 0 "" "")
8183 (call (match_operand 1 "memory_operand" "")
8184 (match_operand 2 "general_operand" "")))
8185 (use (match_operand 3 "" ""))
8186 (clobber (reg:SI LR_REGNUM))])])
8187
8188 (define_expand "nonsecure_call_value_internal"
8189 [(parallel [(set (match_operand 0 "" "")
8190 (call (unspec:SI [(match_operand 1 "memory_operand" "")]
8191 UNSPEC_NONSECURE_MEM)
8192 (match_operand 2 "general_operand" "")))
8193 (use (match_operand 3 "" ""))
8194 (clobber (reg:SI LR_REGNUM))
8195 (clobber (reg:SI 4))])]
8196 "use_cmse"
8197 "
8198 {
8199 rtx tmp;
8200 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
8201 gen_rtx_REG (SImode, 4),
8202 SImode);
8203
8204 operands[1] = replace_equiv_address (operands[1], tmp);
8205 }")
8206
8207 (define_insn "*call_value_reg_armv5"
8208 [(set (match_operand 0 "" "")
8209 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8210 (match_operand 2 "" "")))
8211 (use (match_operand 3 "" ""))
8212 (clobber (reg:SI LR_REGNUM))]
8213 "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
8214 "blx%?\\t%1"
8215 [(set_attr "type" "call")]
8216 )
8217
8218 (define_insn "*call_value_reg_arm"
8219 [(set (match_operand 0 "" "")
8220 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8221 (match_operand 2 "" "")))
8222 (use (match_operand 3 "" ""))
8223 (clobber (reg:SI LR_REGNUM))]
8224 "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
8225 "*
8226 return output_call (&operands[1]);
8227 "
8228 [(set_attr "length" "12")
8229 (set_attr "type" "call")]
8230 )
8231
8232 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8233 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8234
8235 (define_insn "*call_symbol"
8236 [(call (mem:SI (match_operand:SI 0 "" ""))
8237 (match_operand 1 "" ""))
8238 (use (match_operand 2 "" ""))
8239 (clobber (reg:SI LR_REGNUM))]
8240 "TARGET_32BIT
8241 && !SIBLING_CALL_P (insn)
8242 && (GET_CODE (operands[0]) == SYMBOL_REF)
8243 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8244 "*
8245 {
8246 rtx op = operands[0];
8247
8248 /* Switch mode now when possible. */
8249 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8250 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8251 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
8252
8253 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8254 }"
8255 [(set_attr "type" "call")]
8256 )
8257
8258 (define_insn "*call_value_symbol"
8259 [(set (match_operand 0 "" "")
8260 (call (mem:SI (match_operand:SI 1 "" ""))
8261 (match_operand:SI 2 "" "")))
8262 (use (match_operand 3 "" ""))
8263 (clobber (reg:SI LR_REGNUM))]
8264 "TARGET_32BIT
8265 && !SIBLING_CALL_P (insn)
8266 && (GET_CODE (operands[1]) == SYMBOL_REF)
8267 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8268 "*
8269 {
8270 rtx op = operands[1];
8271
8272 /* Switch mode now when possible. */
8273 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
8274 && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
8275 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
8276
8277 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8278 }"
8279 [(set_attr "type" "call")]
8280 )
8281
8282 (define_expand "sibcall_internal"
8283 [(parallel [(call (match_operand 0 "memory_operand" "")
8284 (match_operand 1 "general_operand" ""))
8285 (return)
8286 (use (match_operand 2 "" ""))])])
8287
8288 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
8289 (define_expand "sibcall"
8290 [(parallel [(call (match_operand 0 "memory_operand" "")
8291 (match_operand 1 "general_operand" ""))
8292 (return)
8293 (use (match_operand 2 "" ""))])]
8294 "TARGET_32BIT"
8295 "
8296 {
8297 rtx pat;
8298
8299 if ((!REG_P (XEXP (operands[0], 0))
8300 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
8301 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
8302 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
8303 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8304
8305 if (operands[2] == NULL_RTX)
8306 operands[2] = const0_rtx;
8307
8308 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
8309 arm_emit_call_insn (pat, operands[0], true);
8310 DONE;
8311 }"
8312 )
8313
8314 (define_expand "sibcall_value_internal"
8315 [(parallel [(set (match_operand 0 "" "")
8316 (call (match_operand 1 "memory_operand" "")
8317 (match_operand 2 "general_operand" "")))
8318 (return)
8319 (use (match_operand 3 "" ""))])])
8320
8321 (define_expand "sibcall_value"
8322 [(parallel [(set (match_operand 0 "" "")
8323 (call (match_operand 1 "memory_operand" "")
8324 (match_operand 2 "general_operand" "")))
8325 (return)
8326 (use (match_operand 3 "" ""))])]
8327 "TARGET_32BIT"
8328 "
8329 {
8330 rtx pat;
8331
8332 if ((!REG_P (XEXP (operands[1], 0))
8333 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
8334 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
8335 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
8336 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8337
8338 if (operands[3] == NULL_RTX)
8339 operands[3] = const0_rtx;
8340
8341 pat = gen_sibcall_value_internal (operands[0], operands[1],
8342 operands[2], operands[3]);
8343 arm_emit_call_insn (pat, operands[1], true);
8344 DONE;
8345 }"
8346 )
8347
8348 (define_insn "*sibcall_insn"
8349 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
8350 (match_operand 1 "" ""))
8351 (return)
8352 (use (match_operand 2 "" ""))]
8353 "TARGET_32BIT && SIBLING_CALL_P (insn)"
8354 "*
8355 if (which_alternative == 1)
8356 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8357 else
8358 {
8359 if (arm_arch5 || arm_arch4t)
8360 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
8361 else
8362 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
8363 }
8364 "
8365 [(set_attr "type" "call")]
8366 )
8367
8368 (define_insn "*sibcall_value_insn"
8369 [(set (match_operand 0 "" "")
8370 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
8371 (match_operand 2 "" "")))
8372 (return)
8373 (use (match_operand 3 "" ""))]
8374 "TARGET_32BIT && SIBLING_CALL_P (insn)"
8375 "*
8376 if (which_alternative == 1)
8377 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8378 else
8379 {
8380 if (arm_arch5 || arm_arch4t)
8381 return \"bx%?\\t%1\";
8382 else
8383 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
8384 }
8385 "
8386 [(set_attr "type" "call")]
8387 )
8388
8389 (define_expand "<return_str>return"
8390 [(RETURNS)]
8391 "(TARGET_ARM || (TARGET_THUMB2
8392 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
8393 && !IS_STACKALIGN (arm_current_func_type ())))
8394 <return_cond_false>"
8395 "
8396 {
8397 if (TARGET_THUMB2)
8398 {
8399 thumb2_expand_return (<return_simple_p>);
8400 DONE;
8401 }
8402 }
8403 "
8404 )
8405
8406 ;; Often the return insn will be the same as loading from memory, so set attr
8407 (define_insn "*arm_return"
8408 [(return)]
8409 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8410 "*
8411 {
8412 if (arm_ccfsm_state == 2)
8413 {
8414 arm_ccfsm_state += 2;
8415 return \"\";
8416 }
8417 return output_return_instruction (const_true_rtx, true, false, false);
8418 }"
8419 [(set_attr "type" "load1")
8420 (set_attr "length" "12")
8421 (set_attr "predicable" "yes")]
8422 )
8423
8424 (define_insn "*cond_<return_str>return"
8425 [(set (pc)
8426 (if_then_else (match_operator 0 "arm_comparison_operator"
8427 [(match_operand 1 "cc_register" "") (const_int 0)])
8428 (RETURNS)
8429 (pc)))]
8430 "TARGET_ARM <return_cond_true>"
8431 "*
8432 {
8433 if (arm_ccfsm_state == 2)
8434 {
8435 arm_ccfsm_state += 2;
8436 return \"\";
8437 }
8438 return output_return_instruction (operands[0], true, false,
8439 <return_simple_p>);
8440 }"
8441 [(set_attr "conds" "use")
8442 (set_attr "length" "12")
8443 (set_attr "type" "load1")]
8444 )
8445
8446 (define_insn "*cond_<return_str>return_inverted"
8447 [(set (pc)
8448 (if_then_else (match_operator 0 "arm_comparison_operator"
8449 [(match_operand 1 "cc_register" "") (const_int 0)])
8450 (pc)
8451 (RETURNS)))]
8452 "TARGET_ARM <return_cond_true>"
8453 "*
8454 {
8455 if (arm_ccfsm_state == 2)
8456 {
8457 arm_ccfsm_state += 2;
8458 return \"\";
8459 }
8460 return output_return_instruction (operands[0], true, true,
8461 <return_simple_p>);
8462 }"
8463 [(set_attr "conds" "use")
8464 (set_attr "length" "12")
8465 (set_attr "type" "load1")]
8466 )
8467
8468 (define_insn "*arm_simple_return"
8469 [(simple_return)]
8470 "TARGET_ARM"
8471 "*
8472 {
8473 if (arm_ccfsm_state == 2)
8474 {
8475 arm_ccfsm_state += 2;
8476 return \"\";
8477 }
8478 return output_return_instruction (const_true_rtx, true, false, true);
8479 }"
8480 [(set_attr "type" "branch")
8481 (set_attr "length" "4")
8482 (set_attr "predicable" "yes")]
8483 )
8484
8485 ;; Generate a sequence of instructions to determine if the processor is
8486 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8487 ;; mask.
8488
8489 (define_expand "return_addr_mask"
8490 [(set (match_dup 1)
8491 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8492 (const_int 0)))
8493 (set (match_operand:SI 0 "s_register_operand" "")
8494 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8495 (const_int -1)
8496 (const_int 67108860)))] ; 0x03fffffc
8497 "TARGET_ARM"
8498 "
8499 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8500 ")
8501
8502 (define_insn "*check_arch2"
8503 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8504 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8505 (const_int 0)))]
8506 "TARGET_ARM"
8507 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8508 [(set_attr "length" "8")
8509 (set_attr "conds" "set")
8510 (set_attr "type" "multiple")]
8511 )
8512
8513 ;; Call subroutine returning any type.
8514
8515 (define_expand "untyped_call"
8516 [(parallel [(call (match_operand 0 "" "")
8517 (const_int 0))
8518 (match_operand 1 "" "")
8519 (match_operand 2 "" "")])]
8520 "TARGET_EITHER"
8521 "
8522 {
8523 int i;
8524 rtx par = gen_rtx_PARALLEL (VOIDmode,
8525 rtvec_alloc (XVECLEN (operands[2], 0)));
8526 rtx addr = gen_reg_rtx (Pmode);
8527 rtx mem;
8528 int size = 0;
8529
8530 emit_move_insn (addr, XEXP (operands[1], 0));
8531 mem = change_address (operands[1], BLKmode, addr);
8532
8533 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8534 {
8535 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8536
8537 /* Default code only uses r0 as a return value, but we could
8538 be using anything up to 4 registers. */
8539 if (REGNO (src) == R0_REGNUM)
8540 src = gen_rtx_REG (TImode, R0_REGNUM);
8541
8542 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8543 GEN_INT (size));
8544 size += GET_MODE_SIZE (GET_MODE (src));
8545 }
8546
8547 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
8548
8549 size = 0;
8550
8551 for (i = 0; i < XVECLEN (par, 0); i++)
8552 {
8553 HOST_WIDE_INT offset = 0;
8554 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8555
8556 if (size != 0)
8557 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8558
8559 mem = change_address (mem, GET_MODE (reg), NULL);
8560 if (REGNO (reg) == R0_REGNUM)
8561 {
8562 /* On thumb we have to use a write-back instruction. */
8563 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8564 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8565 size = TARGET_ARM ? 16 : 0;
8566 }
8567 else
8568 {
8569 emit_move_insn (mem, reg);
8570 size = GET_MODE_SIZE (GET_MODE (reg));
8571 }
8572 }
8573
8574 /* The optimizer does not know that the call sets the function value
8575 registers we stored in the result block. We avoid problems by
8576 claiming that all hard registers are used and clobbered at this
8577 point. */
8578 emit_insn (gen_blockage ());
8579
8580 DONE;
8581 }"
8582 )
8583
8584 (define_expand "untyped_return"
8585 [(match_operand:BLK 0 "memory_operand" "")
8586 (match_operand 1 "" "")]
8587 "TARGET_EITHER"
8588 "
8589 {
8590 int i;
8591 rtx addr = gen_reg_rtx (Pmode);
8592 rtx mem;
8593 int size = 0;
8594
8595 emit_move_insn (addr, XEXP (operands[0], 0));
8596 mem = change_address (operands[0], BLKmode, addr);
8597
8598 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8599 {
8600 HOST_WIDE_INT offset = 0;
8601 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8602
8603 if (size != 0)
8604 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8605
8606 mem = change_address (mem, GET_MODE (reg), NULL);
8607 if (REGNO (reg) == R0_REGNUM)
8608 {
8609 /* On thumb we have to use a write-back instruction. */
8610 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8611 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8612 size = TARGET_ARM ? 16 : 0;
8613 }
8614 else
8615 {
8616 emit_move_insn (reg, mem);
8617 size = GET_MODE_SIZE (GET_MODE (reg));
8618 }
8619 }
8620
8621 /* Emit USE insns before the return. */
8622 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8623 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8624
8625 /* Construct the return. */
8626 expand_naked_return ();
8627
8628 DONE;
8629 }"
8630 )
8631
8632 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8633 ;; all of memory. This blocks insns from being moved across this point.
8634
8635 (define_insn "blockage"
8636 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8637 "TARGET_EITHER"
8638 ""
8639 [(set_attr "length" "0")
8640 (set_attr "type" "block")]
8641 )
8642
8643 (define_insn "probe_stack"
8644 [(set (match_operand:SI 0 "memory_operand" "=m")
8645 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
8646 "TARGET_32BIT"
8647 "str%?\\tr0, %0"
8648 [(set_attr "type" "store1")
8649 (set_attr "predicable" "yes")]
8650 )
8651
8652 (define_insn "probe_stack_range"
8653 [(set (match_operand:SI 0 "register_operand" "=r")
8654 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8655 (match_operand:SI 2 "register_operand" "r")]
8656 VUNSPEC_PROBE_STACK_RANGE))]
8657 "TARGET_32BIT"
8658 {
8659 return output_probe_stack_range (operands[0], operands[2]);
8660 }
8661 [(set_attr "type" "multiple")
8662 (set_attr "conds" "clob")]
8663 )
8664
8665 (define_expand "casesi"
8666 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8667 (match_operand:SI 1 "const_int_operand" "") ; lower bound
8668 (match_operand:SI 2 "const_int_operand" "") ; total range
8669 (match_operand:SI 3 "" "") ; table label
8670 (match_operand:SI 4 "" "")] ; Out of range label
8671 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
8672 "
8673 {
8674 enum insn_code code;
8675 if (operands[1] != const0_rtx)
8676 {
8677 rtx reg = gen_reg_rtx (SImode);
8678
8679 emit_insn (gen_addsi3 (reg, operands[0],
8680 gen_int_mode (-INTVAL (operands[1]),
8681 SImode)));
8682 operands[0] = reg;
8683 }
8684
8685 if (TARGET_ARM)
8686 code = CODE_FOR_arm_casesi_internal;
8687 else if (TARGET_THUMB1)
8688 code = CODE_FOR_thumb1_casesi_internal_pic;
8689 else if (flag_pic)
8690 code = CODE_FOR_thumb2_casesi_internal_pic;
8691 else
8692 code = CODE_FOR_thumb2_casesi_internal;
8693
8694 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8695 operands[2] = force_reg (SImode, operands[2]);
8696
8697 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8698 operands[3], operands[4]));
8699 DONE;
8700 }"
8701 )
8702
8703 ;; The USE in this pattern is needed to tell flow analysis that this is
8704 ;; a CASESI insn. It has no other purpose.
8705 (define_insn "arm_casesi_internal"
8706 [(parallel [(set (pc)
8707 (if_then_else
8708 (leu (match_operand:SI 0 "s_register_operand" "r")
8709 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8710 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8711 (label_ref (match_operand 2 "" ""))))
8712 (label_ref (match_operand 3 "" ""))))
8713 (clobber (reg:CC CC_REGNUM))
8714 (use (label_ref (match_dup 2)))])]
8715 "TARGET_ARM"
8716 "*
8717 if (flag_pic)
8718 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8719 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8720 "
8721 [(set_attr "conds" "clob")
8722 (set_attr "length" "12")
8723 (set_attr "type" "multiple")]
8724 )
8725
8726 (define_expand "indirect_jump"
8727 [(set (pc)
8728 (match_operand:SI 0 "s_register_operand" ""))]
8729 "TARGET_EITHER"
8730 "
8731 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8732 address and use bx. */
8733 if (TARGET_THUMB2)
8734 {
8735 rtx tmp;
8736 tmp = gen_reg_rtx (SImode);
8737 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8738 operands[0] = tmp;
8739 }
8740 "
8741 )
8742
8743 ;; NB Never uses BX.
8744 (define_insn "*arm_indirect_jump"
8745 [(set (pc)
8746 (match_operand:SI 0 "s_register_operand" "r"))]
8747 "TARGET_ARM"
8748 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8749 [(set_attr "predicable" "yes")
8750 (set_attr "type" "branch")]
8751 )
8752
8753 (define_insn "*load_indirect_jump"
8754 [(set (pc)
8755 (match_operand:SI 0 "memory_operand" "m"))]
8756 "TARGET_ARM"
8757 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8758 [(set_attr "type" "load1")
8759 (set_attr "pool_range" "4096")
8760 (set_attr "neg_pool_range" "4084")
8761 (set_attr "predicable" "yes")]
8762 )
8763
8764 \f
8765 ;; Misc insns
8766
8767 (define_insn "nop"
8768 [(const_int 0)]
8769 "TARGET_EITHER"
8770 "nop"
8771 [(set (attr "length")
8772 (if_then_else (eq_attr "is_thumb" "yes")
8773 (const_int 2)
8774 (const_int 4)))
8775 (set_attr "type" "mov_reg")]
8776 )
8777
8778 (define_insn "trap"
8779 [(trap_if (const_int 1) (const_int 0))]
8780 ""
8781 "*
8782 if (TARGET_ARM)
8783 return \".inst\\t0xe7f000f0\";
8784 else
8785 return \".inst\\t0xdeff\";
8786 "
8787 [(set (attr "length")
8788 (if_then_else (eq_attr "is_thumb" "yes")
8789 (const_int 2)
8790 (const_int 4)))
8791 (set_attr "type" "trap")
8792 (set_attr "conds" "unconditional")]
8793 )
8794
8795 \f
8796 ;; Patterns to allow combination of arithmetic, cond code and shifts
8797
8798 (define_insn "*<arith_shift_insn>_multsi"
8799 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8800 (SHIFTABLE_OPS:SI
8801 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8802 (match_operand:SI 3 "power_of_two_operand" ""))
8803 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
8804 "TARGET_32BIT"
8805 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8806 [(set_attr "predicable" "yes")
8807 (set_attr "predicable_short_it" "no")
8808 (set_attr "shift" "2")
8809 (set_attr "arch" "a,t2")
8810 (set_attr "type" "alu_shift_imm")])
8811
8812 (define_insn "*<arith_shift_insn>_shiftsi"
8813 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8814 (SHIFTABLE_OPS:SI
8815 (match_operator:SI 2 "shift_nomul_operator"
8816 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8817 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8818 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
8819 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
8820 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
8821 [(set_attr "predicable" "yes")
8822 (set_attr "predicable_short_it" "no")
8823 (set_attr "shift" "3")
8824 (set_attr "arch" "a,t2,a")
8825 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
8826
8827 (define_split
8828 [(set (match_operand:SI 0 "s_register_operand" "")
8829 (match_operator:SI 1 "shiftable_operator"
8830 [(match_operator:SI 2 "shiftable_operator"
8831 [(match_operator:SI 3 "shift_operator"
8832 [(match_operand:SI 4 "s_register_operand" "")
8833 (match_operand:SI 5 "reg_or_int_operand" "")])
8834 (match_operand:SI 6 "s_register_operand" "")])
8835 (match_operand:SI 7 "arm_rhs_operand" "")]))
8836 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8837 "TARGET_32BIT"
8838 [(set (match_dup 8)
8839 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8840 (match_dup 6)]))
8841 (set (match_dup 0)
8842 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8843 "")
8844
8845 (define_insn "*arith_shiftsi_compare0"
8846 [(set (reg:CC_NOOV CC_REGNUM)
8847 (compare:CC_NOOV
8848 (match_operator:SI 1 "shiftable_operator"
8849 [(match_operator:SI 3 "shift_operator"
8850 [(match_operand:SI 4 "s_register_operand" "r,r")
8851 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8852 (match_operand:SI 2 "s_register_operand" "r,r")])
8853 (const_int 0)))
8854 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8855 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8856 (match_dup 2)]))]
8857 "TARGET_32BIT"
8858 "%i1s%?\\t%0, %2, %4%S3"
8859 [(set_attr "conds" "set")
8860 (set_attr "shift" "4")
8861 (set_attr "arch" "32,a")
8862 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8863
8864 (define_insn "*arith_shiftsi_compare0_scratch"
8865 [(set (reg:CC_NOOV CC_REGNUM)
8866 (compare:CC_NOOV
8867 (match_operator:SI 1 "shiftable_operator"
8868 [(match_operator:SI 3 "shift_operator"
8869 [(match_operand:SI 4 "s_register_operand" "r,r")
8870 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8871 (match_operand:SI 2 "s_register_operand" "r,r")])
8872 (const_int 0)))
8873 (clobber (match_scratch:SI 0 "=r,r"))]
8874 "TARGET_32BIT"
8875 "%i1s%?\\t%0, %2, %4%S3"
8876 [(set_attr "conds" "set")
8877 (set_attr "shift" "4")
8878 (set_attr "arch" "32,a")
8879 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8880
8881 (define_insn "*sub_shiftsi"
8882 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8883 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8884 (match_operator:SI 2 "shift_operator"
8885 [(match_operand:SI 3 "s_register_operand" "r,r")
8886 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8887 "TARGET_32BIT"
8888 "sub%?\\t%0, %1, %3%S2"
8889 [(set_attr "predicable" "yes")
8890 (set_attr "shift" "3")
8891 (set_attr "arch" "32,a")
8892 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8893
8894 (define_insn "*sub_shiftsi_compare0"
8895 [(set (reg:CC_NOOV CC_REGNUM)
8896 (compare:CC_NOOV
8897 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8898 (match_operator:SI 2 "shift_operator"
8899 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8900 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8901 (const_int 0)))
8902 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8903 (minus:SI (match_dup 1)
8904 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8905 "TARGET_32BIT"
8906 "subs%?\\t%0, %1, %3%S2"
8907 [(set_attr "conds" "set")
8908 (set_attr "shift" "3")
8909 (set_attr "arch" "32,a,a")
8910 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8911
8912 (define_insn "*sub_shiftsi_compare0_scratch"
8913 [(set (reg:CC_NOOV CC_REGNUM)
8914 (compare:CC_NOOV
8915 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8916 (match_operator:SI 2 "shift_operator"
8917 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8918 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8919 (const_int 0)))
8920 (clobber (match_scratch:SI 0 "=r,r,r"))]
8921 "TARGET_32BIT"
8922 "subs%?\\t%0, %1, %3%S2"
8923 [(set_attr "conds" "set")
8924 (set_attr "shift" "3")
8925 (set_attr "arch" "32,a,a")
8926 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8927 \f
8928
8929 (define_insn_and_split "*and_scc"
8930 [(set (match_operand:SI 0 "s_register_operand" "=r")
8931 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8932 [(match_operand 2 "cc_register" "") (const_int 0)])
8933 (match_operand:SI 3 "s_register_operand" "r")))]
8934 "TARGET_ARM"
8935 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8936 "&& reload_completed"
8937 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8938 (cond_exec (match_dup 4) (set (match_dup 0)
8939 (and:SI (match_dup 3) (const_int 1))))]
8940 {
8941 machine_mode mode = GET_MODE (operands[2]);
8942 enum rtx_code rc = GET_CODE (operands[1]);
8943
8944 /* Note that operands[4] is the same as operands[1],
8945 but with VOIDmode as the result. */
8946 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8947 if (mode == CCFPmode || mode == CCFPEmode)
8948 rc = reverse_condition_maybe_unordered (rc);
8949 else
8950 rc = reverse_condition (rc);
8951 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8952 }
8953 [(set_attr "conds" "use")
8954 (set_attr "type" "multiple")
8955 (set_attr "length" "8")]
8956 )
8957
8958 (define_insn_and_split "*ior_scc"
8959 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8960 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8961 [(match_operand 2 "cc_register" "") (const_int 0)])
8962 (match_operand:SI 3 "s_register_operand" "0,?r")))]
8963 "TARGET_ARM"
8964 "@
8965 orr%d1\\t%0, %3, #1
8966 #"
8967 "&& reload_completed
8968 && REGNO (operands [0]) != REGNO (operands[3])"
8969 ;; && which_alternative == 1
8970 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8971 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8972 (cond_exec (match_dup 4) (set (match_dup 0)
8973 (ior:SI (match_dup 3) (const_int 1))))]
8974 {
8975 machine_mode mode = GET_MODE (operands[2]);
8976 enum rtx_code rc = GET_CODE (operands[1]);
8977
8978 /* Note that operands[4] is the same as operands[1],
8979 but with VOIDmode as the result. */
8980 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8981 if (mode == CCFPmode || mode == CCFPEmode)
8982 rc = reverse_condition_maybe_unordered (rc);
8983 else
8984 rc = reverse_condition (rc);
8985 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8986 }
8987 [(set_attr "conds" "use")
8988 (set_attr "length" "4,8")
8989 (set_attr "type" "logic_imm,multiple")]
8990 )
8991
8992 ; A series of splitters for the compare_scc pattern below. Note that
8993 ; order is important.
8994 (define_split
8995 [(set (match_operand:SI 0 "s_register_operand" "")
8996 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8997 (const_int 0)))
8998 (clobber (reg:CC CC_REGNUM))]
8999 "TARGET_32BIT && reload_completed"
9000 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9001
9002 (define_split
9003 [(set (match_operand:SI 0 "s_register_operand" "")
9004 (ge:SI (match_operand:SI 1 "s_register_operand" "")
9005 (const_int 0)))
9006 (clobber (reg:CC CC_REGNUM))]
9007 "TARGET_32BIT && reload_completed"
9008 [(set (match_dup 0) (not:SI (match_dup 1)))
9009 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9010
9011 (define_split
9012 [(set (match_operand:SI 0 "s_register_operand" "")
9013 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9014 (const_int 0)))
9015 (clobber (reg:CC CC_REGNUM))]
9016 "arm_arch5 && TARGET_32BIT"
9017 [(set (match_dup 0) (clz:SI (match_dup 1)))
9018 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9019 )
9020
9021 (define_split
9022 [(set (match_operand:SI 0 "s_register_operand" "")
9023 (eq:SI (match_operand:SI 1 "s_register_operand" "")
9024 (const_int 0)))
9025 (clobber (reg:CC CC_REGNUM))]
9026 "TARGET_32BIT && reload_completed"
9027 [(parallel
9028 [(set (reg:CC CC_REGNUM)
9029 (compare:CC (const_int 1) (match_dup 1)))
9030 (set (match_dup 0)
9031 (minus:SI (const_int 1) (match_dup 1)))])
9032 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
9033 (set (match_dup 0) (const_int 0)))])
9034
9035 (define_split
9036 [(set (match_operand:SI 0 "s_register_operand" "")
9037 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9038 (match_operand:SI 2 "const_int_operand" "")))
9039 (clobber (reg:CC CC_REGNUM))]
9040 "TARGET_32BIT && reload_completed"
9041 [(parallel
9042 [(set (reg:CC CC_REGNUM)
9043 (compare:CC (match_dup 1) (match_dup 2)))
9044 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9045 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9046 (set (match_dup 0) (const_int 1)))]
9047 {
9048 operands[3] = GEN_INT (-INTVAL (operands[2]));
9049 })
9050
9051 (define_split
9052 [(set (match_operand:SI 0 "s_register_operand" "")
9053 (ne:SI (match_operand:SI 1 "s_register_operand" "")
9054 (match_operand:SI 2 "arm_add_operand" "")))
9055 (clobber (reg:CC CC_REGNUM))]
9056 "TARGET_32BIT && reload_completed"
9057 [(parallel
9058 [(set (reg:CC_NOOV CC_REGNUM)
9059 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9060 (const_int 0)))
9061 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9062 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9063 (set (match_dup 0) (const_int 1)))])
9064
9065 (define_insn_and_split "*compare_scc"
9066 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9067 (match_operator:SI 1 "arm_comparison_operator"
9068 [(match_operand:SI 2 "s_register_operand" "r,r")
9069 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9070 (clobber (reg:CC CC_REGNUM))]
9071 "TARGET_32BIT"
9072 "#"
9073 "&& reload_completed"
9074 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9075 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9076 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9077 {
9078 rtx tmp1;
9079 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9080 operands[2], operands[3]);
9081 enum rtx_code rc = GET_CODE (operands[1]);
9082
9083 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
9084
9085 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9086 if (mode == CCFPmode || mode == CCFPEmode)
9087 rc = reverse_condition_maybe_unordered (rc);
9088 else
9089 rc = reverse_condition (rc);
9090 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9091 }
9092 [(set_attr "type" "multiple")]
9093 )
9094
9095 ;; Attempt to improve the sequence generated by the compare_scc splitters
9096 ;; not to use conditional execution.
9097
9098 ;; Rd = (eq (reg1) (const_int0)) // ARMv5
9099 ;; clz Rd, reg1
9100 ;; lsr Rd, Rd, #5
9101 (define_peephole2
9102 [(set (reg:CC CC_REGNUM)
9103 (compare:CC (match_operand:SI 1 "register_operand" "")
9104 (const_int 0)))
9105 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9106 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9107 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9108 (set (match_dup 0) (const_int 1)))]
9109 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9110 [(set (match_dup 0) (clz:SI (match_dup 1)))
9111 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9112 )
9113
9114 ;; Rd = (eq (reg1) (const_int0)) // !ARMv5
9115 ;; negs Rd, reg1
9116 ;; adc Rd, Rd, reg1
9117 (define_peephole2
9118 [(set (reg:CC CC_REGNUM)
9119 (compare:CC (match_operand:SI 1 "register_operand" "")
9120 (const_int 0)))
9121 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9122 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9123 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9124 (set (match_dup 0) (const_int 1)))
9125 (match_scratch:SI 2 "r")]
9126 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9127 [(parallel
9128 [(set (reg:CC CC_REGNUM)
9129 (compare:CC (const_int 0) (match_dup 1)))
9130 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
9131 (set (match_dup 0)
9132 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
9133 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9134 )
9135
9136 ;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
9137 ;; sub Rd, Reg1, reg2
9138 ;; clz Rd, Rd
9139 ;; lsr Rd, Rd, #5
9140 (define_peephole2
9141 [(set (reg:CC CC_REGNUM)
9142 (compare:CC (match_operand:SI 1 "register_operand" "")
9143 (match_operand:SI 2 "arm_rhs_operand" "")))
9144 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9145 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9146 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9147 (set (match_dup 0) (const_int 1)))]
9148 "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
9149 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
9150 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
9151 (set (match_dup 0) (clz:SI (match_dup 0)))
9152 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
9153 )
9154
9155
9156 ;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
9157 ;; sub T1, Reg1, reg2
9158 ;; negs Rd, T1
9159 ;; adc Rd, Rd, T1
9160 (define_peephole2
9161 [(set (reg:CC CC_REGNUM)
9162 (compare:CC (match_operand:SI 1 "register_operand" "")
9163 (match_operand:SI 2 "arm_rhs_operand" "")))
9164 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9165 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9166 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9167 (set (match_dup 0) (const_int 1)))
9168 (match_scratch:SI 3 "r")]
9169 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
9170 [(set (match_dup 3) (match_dup 4))
9171 (parallel
9172 [(set (reg:CC CC_REGNUM)
9173 (compare:CC (const_int 0) (match_dup 3)))
9174 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
9175 (set (match_dup 0)
9176 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9177 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
9178 "
9179 if (CONST_INT_P (operands[2]))
9180 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
9181 else
9182 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
9183 ")
9184
9185 (define_insn "*cond_move"
9186 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9187 (if_then_else:SI (match_operator 3 "equality_operator"
9188 [(match_operator 4 "arm_comparison_operator"
9189 [(match_operand 5 "cc_register" "") (const_int 0)])
9190 (const_int 0)])
9191 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9192 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9193 "TARGET_ARM"
9194 "*
9195 if (GET_CODE (operands[3]) == NE)
9196 {
9197 if (which_alternative != 1)
9198 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9199 if (which_alternative != 0)
9200 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9201 return \"\";
9202 }
9203 if (which_alternative != 0)
9204 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9205 if (which_alternative != 1)
9206 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9207 return \"\";
9208 "
9209 [(set_attr "conds" "use")
9210 (set_attr_alternative "type"
9211 [(if_then_else (match_operand 2 "const_int_operand" "")
9212 (const_string "mov_imm")
9213 (const_string "mov_reg"))
9214 (if_then_else (match_operand 1 "const_int_operand" "")
9215 (const_string "mov_imm")
9216 (const_string "mov_reg"))
9217 (const_string "multiple")])
9218 (set_attr "length" "4,4,8")]
9219 )
9220
9221 (define_insn "*cond_arith"
9222 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9223 (match_operator:SI 5 "shiftable_operator"
9224 [(match_operator:SI 4 "arm_comparison_operator"
9225 [(match_operand:SI 2 "s_register_operand" "r,r")
9226 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9227 (match_operand:SI 1 "s_register_operand" "0,?r")]))
9228 (clobber (reg:CC CC_REGNUM))]
9229 "TARGET_ARM"
9230 "*
9231 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9232 return \"%i5\\t%0, %1, %2, lsr #31\";
9233
9234 output_asm_insn (\"cmp\\t%2, %3\", operands);
9235 if (GET_CODE (operands[5]) == AND)
9236 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9237 else if (GET_CODE (operands[5]) == MINUS)
9238 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9239 else if (which_alternative != 0)
9240 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9241 return \"%i5%d4\\t%0, %1, #1\";
9242 "
9243 [(set_attr "conds" "clob")
9244 (set_attr "length" "12")
9245 (set_attr "type" "multiple")]
9246 )
9247
9248 (define_insn "*cond_sub"
9249 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9250 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9251 (match_operator:SI 4 "arm_comparison_operator"
9252 [(match_operand:SI 2 "s_register_operand" "r,r")
9253 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9254 (clobber (reg:CC CC_REGNUM))]
9255 "TARGET_ARM"
9256 "*
9257 output_asm_insn (\"cmp\\t%2, %3\", operands);
9258 if (which_alternative != 0)
9259 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9260 return \"sub%d4\\t%0, %1, #1\";
9261 "
9262 [(set_attr "conds" "clob")
9263 (set_attr "length" "8,12")
9264 (set_attr "type" "multiple")]
9265 )
9266
9267 (define_insn "*cmp_ite0"
9268 [(set (match_operand 6 "dominant_cc_register" "")
9269 (compare
9270 (if_then_else:SI
9271 (match_operator 4 "arm_comparison_operator"
9272 [(match_operand:SI 0 "s_register_operand"
9273 "l,l,l,r,r,r,r,r,r")
9274 (match_operand:SI 1 "arm_add_operand"
9275 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9276 (match_operator:SI 5 "arm_comparison_operator"
9277 [(match_operand:SI 2 "s_register_operand"
9278 "l,r,r,l,l,r,r,r,r")
9279 (match_operand:SI 3 "arm_add_operand"
9280 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9281 (const_int 0))
9282 (const_int 0)))]
9283 "TARGET_32BIT"
9284 "*
9285 {
9286 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9287 {
9288 {\"cmp%d5\\t%0, %1\",
9289 \"cmp%d4\\t%2, %3\"},
9290 {\"cmn%d5\\t%0, #%n1\",
9291 \"cmp%d4\\t%2, %3\"},
9292 {\"cmp%d5\\t%0, %1\",
9293 \"cmn%d4\\t%2, #%n3\"},
9294 {\"cmn%d5\\t%0, #%n1\",
9295 \"cmn%d4\\t%2, #%n3\"}
9296 };
9297 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9298 {
9299 {\"cmp\\t%2, %3\",
9300 \"cmp\\t%0, %1\"},
9301 {\"cmp\\t%2, %3\",
9302 \"cmn\\t%0, #%n1\"},
9303 {\"cmn\\t%2, #%n3\",
9304 \"cmp\\t%0, %1\"},
9305 {\"cmn\\t%2, #%n3\",
9306 \"cmn\\t%0, #%n1\"}
9307 };
9308 static const char * const ite[2] =
9309 {
9310 \"it\\t%d5\",
9311 \"it\\t%d4\"
9312 };
9313 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9314 CMP_CMP, CMN_CMP, CMP_CMP,
9315 CMN_CMP, CMP_CMN, CMN_CMN};
9316 int swap =
9317 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9318
9319 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9320 if (TARGET_THUMB2) {
9321 output_asm_insn (ite[swap], operands);
9322 }
9323 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9324 return \"\";
9325 }"
9326 [(set_attr "conds" "set")
9327 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9328 (set_attr "type" "multiple")
9329 (set_attr_alternative "length"
9330 [(const_int 6)
9331 (const_int 8)
9332 (const_int 8)
9333 (const_int 8)
9334 (const_int 8)
9335 (if_then_else (eq_attr "is_thumb" "no")
9336 (const_int 8)
9337 (const_int 10))
9338 (if_then_else (eq_attr "is_thumb" "no")
9339 (const_int 8)
9340 (const_int 10))
9341 (if_then_else (eq_attr "is_thumb" "no")
9342 (const_int 8)
9343 (const_int 10))
9344 (if_then_else (eq_attr "is_thumb" "no")
9345 (const_int 8)
9346 (const_int 10))])]
9347 )
9348
9349 (define_insn "*cmp_ite1"
9350 [(set (match_operand 6 "dominant_cc_register" "")
9351 (compare
9352 (if_then_else:SI
9353 (match_operator 4 "arm_comparison_operator"
9354 [(match_operand:SI 0 "s_register_operand"
9355 "l,l,l,r,r,r,r,r,r")
9356 (match_operand:SI 1 "arm_add_operand"
9357 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9358 (match_operator:SI 5 "arm_comparison_operator"
9359 [(match_operand:SI 2 "s_register_operand"
9360 "l,r,r,l,l,r,r,r,r")
9361 (match_operand:SI 3 "arm_add_operand"
9362 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9363 (const_int 1))
9364 (const_int 0)))]
9365 "TARGET_32BIT"
9366 "*
9367 {
9368 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9369 {
9370 {\"cmp\\t%0, %1\",
9371 \"cmp\\t%2, %3\"},
9372 {\"cmn\\t%0, #%n1\",
9373 \"cmp\\t%2, %3\"},
9374 {\"cmp\\t%0, %1\",
9375 \"cmn\\t%2, #%n3\"},
9376 {\"cmn\\t%0, #%n1\",
9377 \"cmn\\t%2, #%n3\"}
9378 };
9379 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9380 {
9381 {\"cmp%d4\\t%2, %3\",
9382 \"cmp%D5\\t%0, %1\"},
9383 {\"cmp%d4\\t%2, %3\",
9384 \"cmn%D5\\t%0, #%n1\"},
9385 {\"cmn%d4\\t%2, #%n3\",
9386 \"cmp%D5\\t%0, %1\"},
9387 {\"cmn%d4\\t%2, #%n3\",
9388 \"cmn%D5\\t%0, #%n1\"}
9389 };
9390 static const char * const ite[2] =
9391 {
9392 \"it\\t%d4\",
9393 \"it\\t%D5\"
9394 };
9395 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9396 CMP_CMP, CMN_CMP, CMP_CMP,
9397 CMN_CMP, CMP_CMN, CMN_CMN};
9398 int swap =
9399 comparison_dominates_p (GET_CODE (operands[5]),
9400 reverse_condition (GET_CODE (operands[4])));
9401
9402 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9403 if (TARGET_THUMB2) {
9404 output_asm_insn (ite[swap], operands);
9405 }
9406 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9407 return \"\";
9408 }"
9409 [(set_attr "conds" "set")
9410 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9411 (set_attr_alternative "length"
9412 [(const_int 6)
9413 (const_int 8)
9414 (const_int 8)
9415 (const_int 8)
9416 (const_int 8)
9417 (if_then_else (eq_attr "is_thumb" "no")
9418 (const_int 8)
9419 (const_int 10))
9420 (if_then_else (eq_attr "is_thumb" "no")
9421 (const_int 8)
9422 (const_int 10))
9423 (if_then_else (eq_attr "is_thumb" "no")
9424 (const_int 8)
9425 (const_int 10))
9426 (if_then_else (eq_attr "is_thumb" "no")
9427 (const_int 8)
9428 (const_int 10))])
9429 (set_attr "type" "multiple")]
9430 )
9431
9432 (define_insn "*cmp_and"
9433 [(set (match_operand 6 "dominant_cc_register" "")
9434 (compare
9435 (and:SI
9436 (match_operator 4 "arm_comparison_operator"
9437 [(match_operand:SI 0 "s_register_operand"
9438 "l,l,l,r,r,r,r,r,r")
9439 (match_operand:SI 1 "arm_add_operand"
9440 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9441 (match_operator:SI 5 "arm_comparison_operator"
9442 [(match_operand:SI 2 "s_register_operand"
9443 "l,r,r,l,l,r,r,r,r")
9444 (match_operand:SI 3 "arm_add_operand"
9445 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9446 (const_int 0)))]
9447 "TARGET_32BIT"
9448 "*
9449 {
9450 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9451 {
9452 {\"cmp%d5\\t%0, %1\",
9453 \"cmp%d4\\t%2, %3\"},
9454 {\"cmn%d5\\t%0, #%n1\",
9455 \"cmp%d4\\t%2, %3\"},
9456 {\"cmp%d5\\t%0, %1\",
9457 \"cmn%d4\\t%2, #%n3\"},
9458 {\"cmn%d5\\t%0, #%n1\",
9459 \"cmn%d4\\t%2, #%n3\"}
9460 };
9461 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9462 {
9463 {\"cmp\\t%2, %3\",
9464 \"cmp\\t%0, %1\"},
9465 {\"cmp\\t%2, %3\",
9466 \"cmn\\t%0, #%n1\"},
9467 {\"cmn\\t%2, #%n3\",
9468 \"cmp\\t%0, %1\"},
9469 {\"cmn\\t%2, #%n3\",
9470 \"cmn\\t%0, #%n1\"}
9471 };
9472 static const char *const ite[2] =
9473 {
9474 \"it\\t%d5\",
9475 \"it\\t%d4\"
9476 };
9477 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9478 CMP_CMP, CMN_CMP, CMP_CMP,
9479 CMN_CMP, CMP_CMN, CMN_CMN};
9480 int swap =
9481 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9482
9483 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9484 if (TARGET_THUMB2) {
9485 output_asm_insn (ite[swap], operands);
9486 }
9487 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9488 return \"\";
9489 }"
9490 [(set_attr "conds" "set")
9491 (set_attr "predicable" "no")
9492 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9493 (set_attr_alternative "length"
9494 [(const_int 6)
9495 (const_int 8)
9496 (const_int 8)
9497 (const_int 8)
9498 (const_int 8)
9499 (if_then_else (eq_attr "is_thumb" "no")
9500 (const_int 8)
9501 (const_int 10))
9502 (if_then_else (eq_attr "is_thumb" "no")
9503 (const_int 8)
9504 (const_int 10))
9505 (if_then_else (eq_attr "is_thumb" "no")
9506 (const_int 8)
9507 (const_int 10))
9508 (if_then_else (eq_attr "is_thumb" "no")
9509 (const_int 8)
9510 (const_int 10))])
9511 (set_attr "type" "multiple")]
9512 )
9513
9514 (define_insn "*cmp_ior"
9515 [(set (match_operand 6 "dominant_cc_register" "")
9516 (compare
9517 (ior:SI
9518 (match_operator 4 "arm_comparison_operator"
9519 [(match_operand:SI 0 "s_register_operand"
9520 "l,l,l,r,r,r,r,r,r")
9521 (match_operand:SI 1 "arm_add_operand"
9522 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9523 (match_operator:SI 5 "arm_comparison_operator"
9524 [(match_operand:SI 2 "s_register_operand"
9525 "l,r,r,l,l,r,r,r,r")
9526 (match_operand:SI 3 "arm_add_operand"
9527 "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9528 (const_int 0)))]
9529 "TARGET_32BIT"
9530 "*
9531 {
9532 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9533 {
9534 {\"cmp\\t%0, %1\",
9535 \"cmp\\t%2, %3\"},
9536 {\"cmn\\t%0, #%n1\",
9537 \"cmp\\t%2, %3\"},
9538 {\"cmp\\t%0, %1\",
9539 \"cmn\\t%2, #%n3\"},
9540 {\"cmn\\t%0, #%n1\",
9541 \"cmn\\t%2, #%n3\"}
9542 };
9543 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9544 {
9545 {\"cmp%D4\\t%2, %3\",
9546 \"cmp%D5\\t%0, %1\"},
9547 {\"cmp%D4\\t%2, %3\",
9548 \"cmn%D5\\t%0, #%n1\"},
9549 {\"cmn%D4\\t%2, #%n3\",
9550 \"cmp%D5\\t%0, %1\"},
9551 {\"cmn%D4\\t%2, #%n3\",
9552 \"cmn%D5\\t%0, #%n1\"}
9553 };
9554 static const char *const ite[2] =
9555 {
9556 \"it\\t%D4\",
9557 \"it\\t%D5\"
9558 };
9559 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9560 CMP_CMP, CMN_CMP, CMP_CMP,
9561 CMN_CMP, CMP_CMN, CMN_CMN};
9562 int swap =
9563 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9564
9565 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9566 if (TARGET_THUMB2) {
9567 output_asm_insn (ite[swap], operands);
9568 }
9569 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9570 return \"\";
9571 }
9572 "
9573 [(set_attr "conds" "set")
9574 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9575 (set_attr_alternative "length"
9576 [(const_int 6)
9577 (const_int 8)
9578 (const_int 8)
9579 (const_int 8)
9580 (const_int 8)
9581 (if_then_else (eq_attr "is_thumb" "no")
9582 (const_int 8)
9583 (const_int 10))
9584 (if_then_else (eq_attr "is_thumb" "no")
9585 (const_int 8)
9586 (const_int 10))
9587 (if_then_else (eq_attr "is_thumb" "no")
9588 (const_int 8)
9589 (const_int 10))
9590 (if_then_else (eq_attr "is_thumb" "no")
9591 (const_int 8)
9592 (const_int 10))])
9593 (set_attr "type" "multiple")]
9594 )
9595
9596 (define_insn_and_split "*ior_scc_scc"
9597 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
9598 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9599 [(match_operand:SI 1 "s_register_operand" "r")
9600 (match_operand:SI 2 "arm_add_operand" "rIL")])
9601 (match_operator:SI 6 "arm_comparison_operator"
9602 [(match_operand:SI 4 "s_register_operand" "r")
9603 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9604 (clobber (reg:CC CC_REGNUM))]
9605 "TARGET_32BIT
9606 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9607 != CCmode)"
9608 "#"
9609 "TARGET_32BIT && reload_completed"
9610 [(set (match_dup 7)
9611 (compare
9612 (ior:SI
9613 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9614 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9615 (const_int 0)))
9616 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9617 "operands[7]
9618 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9619 DOM_CC_X_OR_Y),
9620 CC_REGNUM);"
9621 [(set_attr "conds" "clob")
9622 (set_attr "length" "16")
9623 (set_attr "type" "multiple")]
9624 )
9625
9626 ; If the above pattern is followed by a CMP insn, then the compare is
9627 ; redundant, since we can rework the conditional instruction that follows.
9628 (define_insn_and_split "*ior_scc_scc_cmp"
9629 [(set (match_operand 0 "dominant_cc_register" "")
9630 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9631 [(match_operand:SI 1 "s_register_operand" "r")
9632 (match_operand:SI 2 "arm_add_operand" "rIL")])
9633 (match_operator:SI 6 "arm_comparison_operator"
9634 [(match_operand:SI 4 "s_register_operand" "r")
9635 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9636 (const_int 0)))
9637 (set (match_operand:SI 7 "s_register_operand" "=Ts")
9638 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9639 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9640 "TARGET_32BIT"
9641 "#"
9642 "TARGET_32BIT && reload_completed"
9643 [(set (match_dup 0)
9644 (compare
9645 (ior:SI
9646 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9647 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9648 (const_int 0)))
9649 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9650 ""
9651 [(set_attr "conds" "set")
9652 (set_attr "length" "16")
9653 (set_attr "type" "multiple")]
9654 )
9655
9656 (define_insn_and_split "*and_scc_scc"
9657 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
9658 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9659 [(match_operand:SI 1 "s_register_operand" "r")
9660 (match_operand:SI 2 "arm_add_operand" "rIL")])
9661 (match_operator:SI 6 "arm_comparison_operator"
9662 [(match_operand:SI 4 "s_register_operand" "r")
9663 (match_operand:SI 5 "arm_add_operand" "rIL")])))
9664 (clobber (reg:CC CC_REGNUM))]
9665 "TARGET_32BIT
9666 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9667 != CCmode)"
9668 "#"
9669 "TARGET_32BIT && reload_completed
9670 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9671 != CCmode)"
9672 [(set (match_dup 7)
9673 (compare
9674 (and:SI
9675 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9676 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9677 (const_int 0)))
9678 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9679 "operands[7]
9680 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9681 DOM_CC_X_AND_Y),
9682 CC_REGNUM);"
9683 [(set_attr "conds" "clob")
9684 (set_attr "length" "16")
9685 (set_attr "type" "multiple")]
9686 )
9687
9688 ; If the above pattern is followed by a CMP insn, then the compare is
9689 ; redundant, since we can rework the conditional instruction that follows.
9690 (define_insn_and_split "*and_scc_scc_cmp"
9691 [(set (match_operand 0 "dominant_cc_register" "")
9692 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9693 [(match_operand:SI 1 "s_register_operand" "r")
9694 (match_operand:SI 2 "arm_add_operand" "rIL")])
9695 (match_operator:SI 6 "arm_comparison_operator"
9696 [(match_operand:SI 4 "s_register_operand" "r")
9697 (match_operand:SI 5 "arm_add_operand" "rIL")]))
9698 (const_int 0)))
9699 (set (match_operand:SI 7 "s_register_operand" "=Ts")
9700 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9701 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9702 "TARGET_32BIT"
9703 "#"
9704 "TARGET_32BIT && reload_completed"
9705 [(set (match_dup 0)
9706 (compare
9707 (and:SI
9708 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9709 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9710 (const_int 0)))
9711 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9712 ""
9713 [(set_attr "conds" "set")
9714 (set_attr "length" "16")
9715 (set_attr "type" "multiple")]
9716 )
9717
9718 ;; If there is no dominance in the comparison, then we can still save an
9719 ;; instruction in the AND case, since we can know that the second compare
9720 ;; need only zero the value if false (if true, then the value is already
9721 ;; correct).
9722 (define_insn_and_split "*and_scc_scc_nodom"
9723 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
9724 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9725 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9726 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9727 (match_operator:SI 6 "arm_comparison_operator"
9728 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9729 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9730 (clobber (reg:CC CC_REGNUM))]
9731 "TARGET_32BIT
9732 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9733 == CCmode)"
9734 "#"
9735 "TARGET_32BIT && reload_completed"
9736 [(parallel [(set (match_dup 0)
9737 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9738 (clobber (reg:CC CC_REGNUM))])
9739 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9740 (set (match_dup 0)
9741 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9742 (match_dup 0)
9743 (const_int 0)))]
9744 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9745 operands[4], operands[5]),
9746 CC_REGNUM);
9747 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9748 operands[5]);"
9749 [(set_attr "conds" "clob")
9750 (set_attr "length" "20")
9751 (set_attr "type" "multiple")]
9752 )
9753
9754 (define_split
9755 [(set (reg:CC_NOOV CC_REGNUM)
9756 (compare:CC_NOOV (ior:SI
9757 (and:SI (match_operand:SI 0 "s_register_operand" "")
9758 (const_int 1))
9759 (match_operator:SI 1 "arm_comparison_operator"
9760 [(match_operand:SI 2 "s_register_operand" "")
9761 (match_operand:SI 3 "arm_add_operand" "")]))
9762 (const_int 0)))
9763 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9764 "TARGET_ARM"
9765 [(set (match_dup 4)
9766 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9767 (match_dup 0)))
9768 (set (reg:CC_NOOV CC_REGNUM)
9769 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9770 (const_int 0)))]
9771 "")
9772
9773 (define_split
9774 [(set (reg:CC_NOOV CC_REGNUM)
9775 (compare:CC_NOOV (ior:SI
9776 (match_operator:SI 1 "arm_comparison_operator"
9777 [(match_operand:SI 2 "s_register_operand" "")
9778 (match_operand:SI 3 "arm_add_operand" "")])
9779 (and:SI (match_operand:SI 0 "s_register_operand" "")
9780 (const_int 1)))
9781 (const_int 0)))
9782 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9783 "TARGET_ARM"
9784 [(set (match_dup 4)
9785 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9786 (match_dup 0)))
9787 (set (reg:CC_NOOV CC_REGNUM)
9788 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9789 (const_int 0)))]
9790 "")
9791 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9792
9793 (define_insn_and_split "*negscc"
9794 [(set (match_operand:SI 0 "s_register_operand" "=r")
9795 (neg:SI (match_operator 3 "arm_comparison_operator"
9796 [(match_operand:SI 1 "s_register_operand" "r")
9797 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9798 (clobber (reg:CC CC_REGNUM))]
9799 "TARGET_ARM"
9800 "#"
9801 "&& reload_completed"
9802 [(const_int 0)]
9803 {
9804 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
9805
9806 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9807 {
9808 /* Emit mov\\t%0, %1, asr #31 */
9809 emit_insn (gen_rtx_SET (operands[0],
9810 gen_rtx_ASHIFTRT (SImode,
9811 operands[1],
9812 GEN_INT (31))));
9813 DONE;
9814 }
9815 else if (GET_CODE (operands[3]) == NE)
9816 {
9817 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9818 if (CONST_INT_P (operands[2]))
9819 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9820 GEN_INT (- INTVAL (operands[2]))));
9821 else
9822 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9823
9824 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9825 gen_rtx_NE (SImode,
9826 cc_reg,
9827 const0_rtx),
9828 gen_rtx_SET (operands[0],
9829 GEN_INT (~0))));
9830 DONE;
9831 }
9832 else
9833 {
9834 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9835 emit_insn (gen_rtx_SET (cc_reg,
9836 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9837 enum rtx_code rc = GET_CODE (operands[3]);
9838
9839 rc = reverse_condition (rc);
9840 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9841 gen_rtx_fmt_ee (rc,
9842 VOIDmode,
9843 cc_reg,
9844 const0_rtx),
9845 gen_rtx_SET (operands[0], const0_rtx)));
9846 rc = GET_CODE (operands[3]);
9847 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9848 gen_rtx_fmt_ee (rc,
9849 VOIDmode,
9850 cc_reg,
9851 const0_rtx),
9852 gen_rtx_SET (operands[0],
9853 GEN_INT (~0))));
9854 DONE;
9855 }
9856 FAIL;
9857 }
9858 [(set_attr "conds" "clob")
9859 (set_attr "length" "12")
9860 (set_attr "type" "multiple")]
9861 )
9862
9863 (define_insn_and_split "movcond_addsi"
9864 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9865 (if_then_else:SI
9866 (match_operator 5 "comparison_operator"
9867 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9868 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9869 (const_int 0)])
9870 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9871 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9872 (clobber (reg:CC CC_REGNUM))]
9873 "TARGET_32BIT"
9874 "#"
9875 "&& reload_completed"
9876 [(set (reg:CC_NOOV CC_REGNUM)
9877 (compare:CC_NOOV
9878 (plus:SI (match_dup 3)
9879 (match_dup 4))
9880 (const_int 0)))
9881 (set (match_dup 0) (match_dup 1))
9882 (cond_exec (match_dup 6)
9883 (set (match_dup 0) (match_dup 2)))]
9884 "
9885 {
9886 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
9887 operands[3], operands[4]);
9888 enum rtx_code rc = GET_CODE (operands[5]);
9889 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9890 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
9891 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
9892 rc = reverse_condition (rc);
9893 else
9894 std::swap (operands[1], operands[2]);
9895
9896 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9897 }
9898 "
9899 [(set_attr "conds" "clob")
9900 (set_attr "enabled_for_depr_it" "no,yes,yes")
9901 (set_attr "type" "multiple")]
9902 )
9903
9904 (define_insn "movcond"
9905 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9906 (if_then_else:SI
9907 (match_operator 5 "arm_comparison_operator"
9908 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9909 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9910 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9911 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9912 (clobber (reg:CC CC_REGNUM))]
9913 "TARGET_ARM"
9914 "*
9915 if (GET_CODE (operands[5]) == LT
9916 && (operands[4] == const0_rtx))
9917 {
9918 if (which_alternative != 1 && REG_P (operands[1]))
9919 {
9920 if (operands[2] == const0_rtx)
9921 return \"and\\t%0, %1, %3, asr #31\";
9922 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9923 }
9924 else if (which_alternative != 0 && REG_P (operands[2]))
9925 {
9926 if (operands[1] == const0_rtx)
9927 return \"bic\\t%0, %2, %3, asr #31\";
9928 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9929 }
9930 /* The only case that falls through to here is when both ops 1 & 2
9931 are constants. */
9932 }
9933
9934 if (GET_CODE (operands[5]) == GE
9935 && (operands[4] == const0_rtx))
9936 {
9937 if (which_alternative != 1 && REG_P (operands[1]))
9938 {
9939 if (operands[2] == const0_rtx)
9940 return \"bic\\t%0, %1, %3, asr #31\";
9941 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9942 }
9943 else if (which_alternative != 0 && REG_P (operands[2]))
9944 {
9945 if (operands[1] == const0_rtx)
9946 return \"and\\t%0, %2, %3, asr #31\";
9947 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9948 }
9949 /* The only case that falls through to here is when both ops 1 & 2
9950 are constants. */
9951 }
9952 if (CONST_INT_P (operands[4])
9953 && !const_ok_for_arm (INTVAL (operands[4])))
9954 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9955 else
9956 output_asm_insn (\"cmp\\t%3, %4\", operands);
9957 if (which_alternative != 0)
9958 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9959 if (which_alternative != 1)
9960 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9961 return \"\";
9962 "
9963 [(set_attr "conds" "clob")
9964 (set_attr "length" "8,8,12")
9965 (set_attr "type" "multiple")]
9966 )
9967
9968 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9969
9970 (define_insn "*ifcompare_plus_move"
9971 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9972 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9973 [(match_operand:SI 4 "s_register_operand" "r,r")
9974 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9975 (plus:SI
9976 (match_operand:SI 2 "s_register_operand" "r,r")
9977 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9978 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9979 (clobber (reg:CC CC_REGNUM))]
9980 "TARGET_ARM"
9981 "#"
9982 [(set_attr "conds" "clob")
9983 (set_attr "length" "8,12")
9984 (set_attr "type" "multiple")]
9985 )
9986
9987 (define_insn "*if_plus_move"
9988 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9989 (if_then_else:SI
9990 (match_operator 4 "arm_comparison_operator"
9991 [(match_operand 5 "cc_register" "") (const_int 0)])
9992 (plus:SI
9993 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9994 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9995 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9996 "TARGET_ARM"
9997 "@
9998 add%d4\\t%0, %2, %3
9999 sub%d4\\t%0, %2, #%n3
10000 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
10001 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
10002 [(set_attr "conds" "use")
10003 (set_attr "length" "4,4,8,8")
10004 (set_attr_alternative "type"
10005 [(if_then_else (match_operand 3 "const_int_operand" "")
10006 (const_string "alu_imm" )
10007 (const_string "alu_sreg"))
10008 (const_string "alu_imm")
10009 (const_string "multiple")
10010 (const_string "multiple")])]
10011 )
10012
10013 (define_insn "*ifcompare_move_plus"
10014 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10015 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10016 [(match_operand:SI 4 "s_register_operand" "r,r")
10017 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10018 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10019 (plus:SI
10020 (match_operand:SI 2 "s_register_operand" "r,r")
10021 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
10022 (clobber (reg:CC CC_REGNUM))]
10023 "TARGET_ARM"
10024 "#"
10025 [(set_attr "conds" "clob")
10026 (set_attr "length" "8,12")
10027 (set_attr "type" "multiple")]
10028 )
10029
10030 (define_insn "*if_move_plus"
10031 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
10032 (if_then_else:SI
10033 (match_operator 4 "arm_comparison_operator"
10034 [(match_operand 5 "cc_register" "") (const_int 0)])
10035 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
10036 (plus:SI
10037 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
10038 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
10039 "TARGET_ARM"
10040 "@
10041 add%D4\\t%0, %2, %3
10042 sub%D4\\t%0, %2, #%n3
10043 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
10044 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
10045 [(set_attr "conds" "use")
10046 (set_attr "length" "4,4,8,8")
10047 (set_attr_alternative "type"
10048 [(if_then_else (match_operand 3 "const_int_operand" "")
10049 (const_string "alu_imm" )
10050 (const_string "alu_sreg"))
10051 (const_string "alu_imm")
10052 (const_string "multiple")
10053 (const_string "multiple")])]
10054 )
10055
10056 (define_insn "*ifcompare_arith_arith"
10057 [(set (match_operand:SI 0 "s_register_operand" "=r")
10058 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
10059 [(match_operand:SI 5 "s_register_operand" "r")
10060 (match_operand:SI 6 "arm_add_operand" "rIL")])
10061 (match_operator:SI 8 "shiftable_operator"
10062 [(match_operand:SI 1 "s_register_operand" "r")
10063 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10064 (match_operator:SI 7 "shiftable_operator"
10065 [(match_operand:SI 3 "s_register_operand" "r")
10066 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
10067 (clobber (reg:CC CC_REGNUM))]
10068 "TARGET_ARM"
10069 "#"
10070 [(set_attr "conds" "clob")
10071 (set_attr "length" "12")
10072 (set_attr "type" "multiple")]
10073 )
10074
10075 (define_insn "*if_arith_arith"
10076 [(set (match_operand:SI 0 "s_register_operand" "=r")
10077 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
10078 [(match_operand 8 "cc_register" "") (const_int 0)])
10079 (match_operator:SI 6 "shiftable_operator"
10080 [(match_operand:SI 1 "s_register_operand" "r")
10081 (match_operand:SI 2 "arm_rhs_operand" "rI")])
10082 (match_operator:SI 7 "shiftable_operator"
10083 [(match_operand:SI 3 "s_register_operand" "r")
10084 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
10085 "TARGET_ARM"
10086 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
10087 [(set_attr "conds" "use")
10088 (set_attr "length" "8")
10089 (set_attr "type" "multiple")]
10090 )
10091
10092 (define_insn "*ifcompare_arith_move"
10093 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10094 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10095 [(match_operand:SI 2 "s_register_operand" "r,r")
10096 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
10097 (match_operator:SI 7 "shiftable_operator"
10098 [(match_operand:SI 4 "s_register_operand" "r,r")
10099 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
10100 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
10101 (clobber (reg:CC CC_REGNUM))]
10102 "TARGET_ARM"
10103 "*
10104 /* If we have an operation where (op x 0) is the identity operation and
10105 the conditional operator is LT or GE and we are comparing against zero and
10106 everything is in registers then we can do this in two instructions. */
10107 if (operands[3] == const0_rtx
10108 && GET_CODE (operands[7]) != AND
10109 && REG_P (operands[5])
10110 && REG_P (operands[1])
10111 && REGNO (operands[1]) == REGNO (operands[4])
10112 && REGNO (operands[4]) != REGNO (operands[0]))
10113 {
10114 if (GET_CODE (operands[6]) == LT)
10115 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10116 else if (GET_CODE (operands[6]) == GE)
10117 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
10118 }
10119 if (CONST_INT_P (operands[3])
10120 && !const_ok_for_arm (INTVAL (operands[3])))
10121 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
10122 else
10123 output_asm_insn (\"cmp\\t%2, %3\", operands);
10124 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
10125 if (which_alternative != 0)
10126 return \"mov%D6\\t%0, %1\";
10127 return \"\";
10128 "
10129 [(set_attr "conds" "clob")
10130 (set_attr "length" "8,12")
10131 (set_attr "type" "multiple")]
10132 )
10133
10134 (define_insn "*if_arith_move"
10135 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10136 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10137 [(match_operand 6 "cc_register" "") (const_int 0)])
10138 (match_operator:SI 5 "shiftable_operator"
10139 [(match_operand:SI 2 "s_register_operand" "r,r")
10140 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10141 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
10142 "TARGET_ARM"
10143 "@
10144 %I5%d4\\t%0, %2, %3
10145 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
10146 [(set_attr "conds" "use")
10147 (set_attr "length" "4,8")
10148 (set_attr_alternative "type"
10149 [(if_then_else (match_operand 3 "const_int_operand" "")
10150 (const_string "alu_shift_imm" )
10151 (const_string "alu_shift_reg"))
10152 (const_string "multiple")])]
10153 )
10154
10155 (define_insn "*ifcompare_move_arith"
10156 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10157 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10158 [(match_operand:SI 4 "s_register_operand" "r,r")
10159 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10160 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10161 (match_operator:SI 7 "shiftable_operator"
10162 [(match_operand:SI 2 "s_register_operand" "r,r")
10163 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
10164 (clobber (reg:CC CC_REGNUM))]
10165 "TARGET_ARM"
10166 "*
10167 /* If we have an operation where (op x 0) is the identity operation and
10168 the conditional operator is LT or GE and we are comparing against zero and
10169 everything is in registers then we can do this in two instructions */
10170 if (operands[5] == const0_rtx
10171 && GET_CODE (operands[7]) != AND
10172 && REG_P (operands[3])
10173 && REG_P (operands[1])
10174 && REGNO (operands[1]) == REGNO (operands[2])
10175 && REGNO (operands[2]) != REGNO (operands[0]))
10176 {
10177 if (GET_CODE (operands[6]) == GE)
10178 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10179 else if (GET_CODE (operands[6]) == LT)
10180 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10181 }
10182
10183 if (CONST_INT_P (operands[5])
10184 && !const_ok_for_arm (INTVAL (operands[5])))
10185 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10186 else
10187 output_asm_insn (\"cmp\\t%4, %5\", operands);
10188
10189 if (which_alternative != 0)
10190 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10191 return \"%I7%D6\\t%0, %2, %3\";
10192 "
10193 [(set_attr "conds" "clob")
10194 (set_attr "length" "8,12")
10195 (set_attr "type" "multiple")]
10196 )
10197
10198 (define_insn "*if_move_arith"
10199 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10200 (if_then_else:SI
10201 (match_operator 4 "arm_comparison_operator"
10202 [(match_operand 6 "cc_register" "") (const_int 0)])
10203 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10204 (match_operator:SI 5 "shiftable_operator"
10205 [(match_operand:SI 2 "s_register_operand" "r,r")
10206 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10207 "TARGET_ARM"
10208 "@
10209 %I5%D4\\t%0, %2, %3
10210 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10211 [(set_attr "conds" "use")
10212 (set_attr "length" "4,8")
10213 (set_attr_alternative "type"
10214 [(if_then_else (match_operand 3 "const_int_operand" "")
10215 (const_string "alu_shift_imm" )
10216 (const_string "alu_shift_reg"))
10217 (const_string "multiple")])]
10218 )
10219
10220 (define_insn "*ifcompare_move_not"
10221 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10222 (if_then_else:SI
10223 (match_operator 5 "arm_comparison_operator"
10224 [(match_operand:SI 3 "s_register_operand" "r,r")
10225 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10226 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10227 (not:SI
10228 (match_operand:SI 2 "s_register_operand" "r,r"))))
10229 (clobber (reg:CC CC_REGNUM))]
10230 "TARGET_ARM"
10231 "#"
10232 [(set_attr "conds" "clob")
10233 (set_attr "length" "8,12")
10234 (set_attr "type" "multiple")]
10235 )
10236
10237 (define_insn "*if_move_not"
10238 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10239 (if_then_else:SI
10240 (match_operator 4 "arm_comparison_operator"
10241 [(match_operand 3 "cc_register" "") (const_int 0)])
10242 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10243 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10244 "TARGET_ARM"
10245 "@
10246 mvn%D4\\t%0, %2
10247 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10248 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10249 [(set_attr "conds" "use")
10250 (set_attr "type" "mvn_reg")
10251 (set_attr "length" "4,8,8")
10252 (set_attr "type" "mvn_reg,multiple,multiple")]
10253 )
10254
10255 (define_insn "*ifcompare_not_move"
10256 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10257 (if_then_else:SI
10258 (match_operator 5 "arm_comparison_operator"
10259 [(match_operand:SI 3 "s_register_operand" "r,r")
10260 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10261 (not:SI
10262 (match_operand:SI 2 "s_register_operand" "r,r"))
10263 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10264 (clobber (reg:CC CC_REGNUM))]
10265 "TARGET_ARM"
10266 "#"
10267 [(set_attr "conds" "clob")
10268 (set_attr "length" "8,12")
10269 (set_attr "type" "multiple")]
10270 )
10271
10272 (define_insn "*if_not_move"
10273 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10274 (if_then_else:SI
10275 (match_operator 4 "arm_comparison_operator"
10276 [(match_operand 3 "cc_register" "") (const_int 0)])
10277 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10278 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10279 "TARGET_ARM"
10280 "@
10281 mvn%d4\\t%0, %2
10282 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10283 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10284 [(set_attr "conds" "use")
10285 (set_attr "type" "mvn_reg,multiple,multiple")
10286 (set_attr "length" "4,8,8")]
10287 )
10288
10289 (define_insn "*ifcompare_shift_move"
10290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10291 (if_then_else:SI
10292 (match_operator 6 "arm_comparison_operator"
10293 [(match_operand:SI 4 "s_register_operand" "r,r")
10294 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10295 (match_operator:SI 7 "shift_operator"
10296 [(match_operand:SI 2 "s_register_operand" "r,r")
10297 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10298 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10299 (clobber (reg:CC CC_REGNUM))]
10300 "TARGET_ARM"
10301 "#"
10302 [(set_attr "conds" "clob")
10303 (set_attr "length" "8,12")
10304 (set_attr "type" "multiple")]
10305 )
10306
10307 (define_insn "*if_shift_move"
10308 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10309 (if_then_else:SI
10310 (match_operator 5 "arm_comparison_operator"
10311 [(match_operand 6 "cc_register" "") (const_int 0)])
10312 (match_operator:SI 4 "shift_operator"
10313 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10314 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10315 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10316 "TARGET_ARM"
10317 "@
10318 mov%d5\\t%0, %2%S4
10319 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10320 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10321 [(set_attr "conds" "use")
10322 (set_attr "shift" "2")
10323 (set_attr "length" "4,8,8")
10324 (set_attr_alternative "type"
10325 [(if_then_else (match_operand 3 "const_int_operand" "")
10326 (const_string "mov_shift" )
10327 (const_string "mov_shift_reg"))
10328 (const_string "multiple")
10329 (const_string "multiple")])]
10330 )
10331
10332 (define_insn "*ifcompare_move_shift"
10333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10334 (if_then_else:SI
10335 (match_operator 6 "arm_comparison_operator"
10336 [(match_operand:SI 4 "s_register_operand" "r,r")
10337 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10338 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10339 (match_operator:SI 7 "shift_operator"
10340 [(match_operand:SI 2 "s_register_operand" "r,r")
10341 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10342 (clobber (reg:CC CC_REGNUM))]
10343 "TARGET_ARM"
10344 "#"
10345 [(set_attr "conds" "clob")
10346 (set_attr "length" "8,12")
10347 (set_attr "type" "multiple")]
10348 )
10349
10350 (define_insn "*if_move_shift"
10351 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10352 (if_then_else:SI
10353 (match_operator 5 "arm_comparison_operator"
10354 [(match_operand 6 "cc_register" "") (const_int 0)])
10355 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10356 (match_operator:SI 4 "shift_operator"
10357 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10358 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10359 "TARGET_ARM"
10360 "@
10361 mov%D5\\t%0, %2%S4
10362 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10363 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10364 [(set_attr "conds" "use")
10365 (set_attr "shift" "2")
10366 (set_attr "length" "4,8,8")
10367 (set_attr_alternative "type"
10368 [(if_then_else (match_operand 3 "const_int_operand" "")
10369 (const_string "mov_shift" )
10370 (const_string "mov_shift_reg"))
10371 (const_string "multiple")
10372 (const_string "multiple")])]
10373 )
10374
10375 (define_insn "*ifcompare_shift_shift"
10376 [(set (match_operand:SI 0 "s_register_operand" "=r")
10377 (if_then_else:SI
10378 (match_operator 7 "arm_comparison_operator"
10379 [(match_operand:SI 5 "s_register_operand" "r")
10380 (match_operand:SI 6 "arm_add_operand" "rIL")])
10381 (match_operator:SI 8 "shift_operator"
10382 [(match_operand:SI 1 "s_register_operand" "r")
10383 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10384 (match_operator:SI 9 "shift_operator"
10385 [(match_operand:SI 3 "s_register_operand" "r")
10386 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10387 (clobber (reg:CC CC_REGNUM))]
10388 "TARGET_ARM"
10389 "#"
10390 [(set_attr "conds" "clob")
10391 (set_attr "length" "12")
10392 (set_attr "type" "multiple")]
10393 )
10394
10395 (define_insn "*if_shift_shift"
10396 [(set (match_operand:SI 0 "s_register_operand" "=r")
10397 (if_then_else:SI
10398 (match_operator 5 "arm_comparison_operator"
10399 [(match_operand 8 "cc_register" "") (const_int 0)])
10400 (match_operator:SI 6 "shift_operator"
10401 [(match_operand:SI 1 "s_register_operand" "r")
10402 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10403 (match_operator:SI 7 "shift_operator"
10404 [(match_operand:SI 3 "s_register_operand" "r")
10405 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10406 "TARGET_ARM"
10407 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10408 [(set_attr "conds" "use")
10409 (set_attr "shift" "1")
10410 (set_attr "length" "8")
10411 (set (attr "type") (if_then_else
10412 (and (match_operand 2 "const_int_operand" "")
10413 (match_operand 4 "const_int_operand" ""))
10414 (const_string "mov_shift")
10415 (const_string "mov_shift_reg")))]
10416 )
10417
10418 (define_insn "*ifcompare_not_arith"
10419 [(set (match_operand:SI 0 "s_register_operand" "=r")
10420 (if_then_else:SI
10421 (match_operator 6 "arm_comparison_operator"
10422 [(match_operand:SI 4 "s_register_operand" "r")
10423 (match_operand:SI 5 "arm_add_operand" "rIL")])
10424 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10425 (match_operator:SI 7 "shiftable_operator"
10426 [(match_operand:SI 2 "s_register_operand" "r")
10427 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10428 (clobber (reg:CC CC_REGNUM))]
10429 "TARGET_ARM"
10430 "#"
10431 [(set_attr "conds" "clob")
10432 (set_attr "length" "12")
10433 (set_attr "type" "multiple")]
10434 )
10435
10436 (define_insn "*if_not_arith"
10437 [(set (match_operand:SI 0 "s_register_operand" "=r")
10438 (if_then_else:SI
10439 (match_operator 5 "arm_comparison_operator"
10440 [(match_operand 4 "cc_register" "") (const_int 0)])
10441 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10442 (match_operator:SI 6 "shiftable_operator"
10443 [(match_operand:SI 2 "s_register_operand" "r")
10444 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10445 "TARGET_ARM"
10446 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10447 [(set_attr "conds" "use")
10448 (set_attr "type" "mvn_reg")
10449 (set_attr "length" "8")]
10450 )
10451
10452 (define_insn "*ifcompare_arith_not"
10453 [(set (match_operand:SI 0 "s_register_operand" "=r")
10454 (if_then_else:SI
10455 (match_operator 6 "arm_comparison_operator"
10456 [(match_operand:SI 4 "s_register_operand" "r")
10457 (match_operand:SI 5 "arm_add_operand" "rIL")])
10458 (match_operator:SI 7 "shiftable_operator"
10459 [(match_operand:SI 2 "s_register_operand" "r")
10460 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10461 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10462 (clobber (reg:CC CC_REGNUM))]
10463 "TARGET_ARM"
10464 "#"
10465 [(set_attr "conds" "clob")
10466 (set_attr "length" "12")
10467 (set_attr "type" "multiple")]
10468 )
10469
10470 (define_insn "*if_arith_not"
10471 [(set (match_operand:SI 0 "s_register_operand" "=r")
10472 (if_then_else:SI
10473 (match_operator 5 "arm_comparison_operator"
10474 [(match_operand 4 "cc_register" "") (const_int 0)])
10475 (match_operator:SI 6 "shiftable_operator"
10476 [(match_operand:SI 2 "s_register_operand" "r")
10477 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10478 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10479 "TARGET_ARM"
10480 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10481 [(set_attr "conds" "use")
10482 (set_attr "type" "multiple")
10483 (set_attr "length" "8")]
10484 )
10485
10486 (define_insn "*ifcompare_neg_move"
10487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10488 (if_then_else:SI
10489 (match_operator 5 "arm_comparison_operator"
10490 [(match_operand:SI 3 "s_register_operand" "r,r")
10491 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10492 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10493 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
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_and_split "*if_neg_move"
10503 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10504 (if_then_else:SI
10505 (match_operator 4 "arm_comparison_operator"
10506 [(match_operand 3 "cc_register" "") (const_int 0)])
10507 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10508 (match_operand:SI 1 "s_register_operand" "0,0")))]
10509 "TARGET_32BIT"
10510 "#"
10511 "&& reload_completed"
10512 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10513 (set (match_dup 0) (neg:SI (match_dup 2))))]
10514 ""
10515 [(set_attr "conds" "use")
10516 (set_attr "length" "4")
10517 (set_attr "arch" "t2,32")
10518 (set_attr "enabled_for_depr_it" "yes,no")
10519 (set_attr "type" "logic_shift_imm")]
10520 )
10521
10522 (define_insn "*ifcompare_move_neg"
10523 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10524 (if_then_else:SI
10525 (match_operator 5 "arm_comparison_operator"
10526 [(match_operand:SI 3 "s_register_operand" "r,r")
10527 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10528 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10529 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10530 (clobber (reg:CC CC_REGNUM))]
10531 "TARGET_ARM"
10532 "#"
10533 [(set_attr "conds" "clob")
10534 (set_attr "length" "8,12")
10535 (set_attr "type" "multiple")]
10536 )
10537
10538 (define_insn_and_split "*if_move_neg"
10539 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10540 (if_then_else:SI
10541 (match_operator 4 "arm_comparison_operator"
10542 [(match_operand 3 "cc_register" "") (const_int 0)])
10543 (match_operand:SI 1 "s_register_operand" "0,0")
10544 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10545 "TARGET_32BIT"
10546 "#"
10547 "&& reload_completed"
10548 [(cond_exec (match_dup 5)
10549 (set (match_dup 0) (neg:SI (match_dup 2))))]
10550 {
10551 machine_mode mode = GET_MODE (operands[3]);
10552 rtx_code rc = GET_CODE (operands[4]);
10553
10554 if (mode == CCFPmode || mode == CCFPEmode)
10555 rc = reverse_condition_maybe_unordered (rc);
10556 else
10557 rc = reverse_condition (rc);
10558
10559 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10560 }
10561 [(set_attr "conds" "use")
10562 (set_attr "length" "4")
10563 (set_attr "arch" "t2,32")
10564 (set_attr "enabled_for_depr_it" "yes,no")
10565 (set_attr "type" "logic_shift_imm")]
10566 )
10567
10568 (define_insn "*arith_adjacentmem"
10569 [(set (match_operand:SI 0 "s_register_operand" "=r")
10570 (match_operator:SI 1 "shiftable_operator"
10571 [(match_operand:SI 2 "memory_operand" "m")
10572 (match_operand:SI 3 "memory_operand" "m")]))
10573 (clobber (match_scratch:SI 4 "=r"))]
10574 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10575 "*
10576 {
10577 rtx ldm[3];
10578 rtx arith[4];
10579 rtx base_reg;
10580 HOST_WIDE_INT val1 = 0, val2 = 0;
10581
10582 if (REGNO (operands[0]) > REGNO (operands[4]))
10583 {
10584 ldm[1] = operands[4];
10585 ldm[2] = operands[0];
10586 }
10587 else
10588 {
10589 ldm[1] = operands[0];
10590 ldm[2] = operands[4];
10591 }
10592
10593 base_reg = XEXP (operands[2], 0);
10594
10595 if (!REG_P (base_reg))
10596 {
10597 val1 = INTVAL (XEXP (base_reg, 1));
10598 base_reg = XEXP (base_reg, 0);
10599 }
10600
10601 if (!REG_P (XEXP (operands[3], 0)))
10602 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10603
10604 arith[0] = operands[0];
10605 arith[3] = operands[1];
10606
10607 if (val1 < val2)
10608 {
10609 arith[1] = ldm[1];
10610 arith[2] = ldm[2];
10611 }
10612 else
10613 {
10614 arith[1] = ldm[2];
10615 arith[2] = ldm[1];
10616 }
10617
10618 ldm[0] = base_reg;
10619 if (val1 !=0 && val2 != 0)
10620 {
10621 rtx ops[3];
10622
10623 if (val1 == 4 || val2 == 4)
10624 /* Other val must be 8, since we know they are adjacent and neither
10625 is zero. */
10626 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
10627 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10628 {
10629 ldm[0] = ops[0] = operands[4];
10630 ops[1] = base_reg;
10631 ops[2] = GEN_INT (val1);
10632 output_add_immediate (ops);
10633 if (val1 < val2)
10634 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10635 else
10636 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10637 }
10638 else
10639 {
10640 /* Offset is out of range for a single add, so use two ldr. */
10641 ops[0] = ldm[1];
10642 ops[1] = base_reg;
10643 ops[2] = GEN_INT (val1);
10644 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10645 ops[0] = ldm[2];
10646 ops[2] = GEN_INT (val2);
10647 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10648 }
10649 }
10650 else if (val1 != 0)
10651 {
10652 if (val1 < val2)
10653 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10654 else
10655 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10656 }
10657 else
10658 {
10659 if (val1 < val2)
10660 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10661 else
10662 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10663 }
10664 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10665 return \"\";
10666 }"
10667 [(set_attr "length" "12")
10668 (set_attr "predicable" "yes")
10669 (set_attr "type" "load1")]
10670 )
10671
10672 ; This pattern is never tried by combine, so do it as a peephole
10673
10674 (define_peephole2
10675 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10676 (match_operand:SI 1 "arm_general_register_operand" ""))
10677 (set (reg:CC CC_REGNUM)
10678 (compare:CC (match_dup 1) (const_int 0)))]
10679 "TARGET_ARM"
10680 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10681 (set (match_dup 0) (match_dup 1))])]
10682 ""
10683 )
10684
10685 (define_split
10686 [(set (match_operand:SI 0 "s_register_operand" "")
10687 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10688 (const_int 0))
10689 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10690 [(match_operand:SI 3 "s_register_operand" "")
10691 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10692 (clobber (match_operand:SI 5 "s_register_operand" ""))]
10693 "TARGET_ARM"
10694 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10695 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10696 (match_dup 5)))]
10697 ""
10698 )
10699
10700 ;; This split can be used because CC_Z mode implies that the following
10701 ;; branch will be an equality, or an unsigned inequality, so the sign
10702 ;; extension is not needed.
10703
10704 (define_split
10705 [(set (reg:CC_Z CC_REGNUM)
10706 (compare:CC_Z
10707 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10708 (const_int 24))
10709 (match_operand 1 "const_int_operand" "")))
10710 (clobber (match_scratch:SI 2 ""))]
10711 "TARGET_ARM
10712 && ((UINTVAL (operands[1]))
10713 == ((UINTVAL (operands[1])) >> 24) << 24)"
10714 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10715 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10716 "
10717 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10718 "
10719 )
10720 ;; ??? Check the patterns above for Thumb-2 usefulness
10721
10722 (define_expand "prologue"
10723 [(clobber (const_int 0))]
10724 "TARGET_EITHER"
10725 "if (TARGET_32BIT)
10726 arm_expand_prologue ();
10727 else
10728 thumb1_expand_prologue ();
10729 DONE;
10730 "
10731 )
10732
10733 (define_expand "epilogue"
10734 [(clobber (const_int 0))]
10735 "TARGET_EITHER"
10736 "
10737 if (crtl->calls_eh_return)
10738 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
10739 if (TARGET_THUMB1)
10740 {
10741 thumb1_expand_epilogue ();
10742 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10743 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10744 }
10745 else if (HAVE_return)
10746 {
10747 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10748 no need for explicit testing again. */
10749 emit_jump_insn (gen_return ());
10750 }
10751 else if (TARGET_32BIT)
10752 {
10753 arm_expand_epilogue (true);
10754 }
10755 DONE;
10756 "
10757 )
10758
10759 ;; Note - although unspec_volatile's USE all hard registers,
10760 ;; USEs are ignored after relaod has completed. Thus we need
10761 ;; to add an unspec of the link register to ensure that flow
10762 ;; does not think that it is unused by the sibcall branch that
10763 ;; will replace the standard function epilogue.
10764 (define_expand "sibcall_epilogue"
10765 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
10766 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10767 "TARGET_32BIT"
10768 "
10769 arm_expand_epilogue (false);
10770 DONE;
10771 "
10772 )
10773
10774 (define_expand "eh_epilogue"
10775 [(use (match_operand:SI 0 "register_operand" ""))
10776 (use (match_operand:SI 1 "register_operand" ""))
10777 (use (match_operand:SI 2 "register_operand" ""))]
10778 "TARGET_EITHER"
10779 "
10780 {
10781 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10782 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
10783 {
10784 rtx ra = gen_rtx_REG (Pmode, 2);
10785
10786 emit_move_insn (ra, operands[2]);
10787 operands[2] = ra;
10788 }
10789 /* This is a hack -- we may have crystalized the function type too
10790 early. */
10791 cfun->machine->func_type = 0;
10792 }"
10793 )
10794
10795 ;; This split is only used during output to reduce the number of patterns
10796 ;; that need assembler instructions adding to them. We allowed the setting
10797 ;; of the conditions to be implicit during rtl generation so that
10798 ;; the conditional compare patterns would work. However this conflicts to
10799 ;; some extent with the conditional data operations, so we have to split them
10800 ;; up again here.
10801
10802 ;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10803 ;; conditional execution sufficient?
10804
10805 (define_split
10806 [(set (match_operand:SI 0 "s_register_operand" "")
10807 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10808 [(match_operand 2 "" "") (match_operand 3 "" "")])
10809 (match_dup 0)
10810 (match_operand 4 "" "")))
10811 (clobber (reg:CC CC_REGNUM))]
10812 "TARGET_ARM && reload_completed"
10813 [(set (match_dup 5) (match_dup 6))
10814 (cond_exec (match_dup 7)
10815 (set (match_dup 0) (match_dup 4)))]
10816 "
10817 {
10818 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10819 operands[2], operands[3]);
10820 enum rtx_code rc = GET_CODE (operands[1]);
10821
10822 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10823 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10824 if (mode == CCFPmode || mode == CCFPEmode)
10825 rc = reverse_condition_maybe_unordered (rc);
10826 else
10827 rc = reverse_condition (rc);
10828
10829 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10830 }"
10831 )
10832
10833 (define_split
10834 [(set (match_operand:SI 0 "s_register_operand" "")
10835 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10836 [(match_operand 2 "" "") (match_operand 3 "" "")])
10837 (match_operand 4 "" "")
10838 (match_dup 0)))
10839 (clobber (reg:CC CC_REGNUM))]
10840 "TARGET_ARM && reload_completed"
10841 [(set (match_dup 5) (match_dup 6))
10842 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10843 (set (match_dup 0) (match_dup 4)))]
10844 "
10845 {
10846 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10847 operands[2], operands[3]);
10848
10849 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10850 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10851 }"
10852 )
10853
10854 (define_split
10855 [(set (match_operand:SI 0 "s_register_operand" "")
10856 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10857 [(match_operand 2 "" "") (match_operand 3 "" "")])
10858 (match_operand 4 "" "")
10859 (match_operand 5 "" "")))
10860 (clobber (reg:CC CC_REGNUM))]
10861 "TARGET_ARM && reload_completed"
10862 [(set (match_dup 6) (match_dup 7))
10863 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10864 (set (match_dup 0) (match_dup 4)))
10865 (cond_exec (match_dup 8)
10866 (set (match_dup 0) (match_dup 5)))]
10867 "
10868 {
10869 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10870 operands[2], operands[3]);
10871 enum rtx_code rc = GET_CODE (operands[1]);
10872
10873 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10874 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10875 if (mode == CCFPmode || mode == CCFPEmode)
10876 rc = reverse_condition_maybe_unordered (rc);
10877 else
10878 rc = reverse_condition (rc);
10879
10880 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10881 }"
10882 )
10883
10884 (define_split
10885 [(set (match_operand:SI 0 "s_register_operand" "")
10886 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10887 [(match_operand:SI 2 "s_register_operand" "")
10888 (match_operand:SI 3 "arm_add_operand" "")])
10889 (match_operand:SI 4 "arm_rhs_operand" "")
10890 (not:SI
10891 (match_operand:SI 5 "s_register_operand" ""))))
10892 (clobber (reg:CC CC_REGNUM))]
10893 "TARGET_ARM && reload_completed"
10894 [(set (match_dup 6) (match_dup 7))
10895 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10896 (set (match_dup 0) (match_dup 4)))
10897 (cond_exec (match_dup 8)
10898 (set (match_dup 0) (not:SI (match_dup 5))))]
10899 "
10900 {
10901 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10902 operands[2], operands[3]);
10903 enum rtx_code rc = GET_CODE (operands[1]);
10904
10905 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10906 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10907 if (mode == CCFPmode || mode == CCFPEmode)
10908 rc = reverse_condition_maybe_unordered (rc);
10909 else
10910 rc = reverse_condition (rc);
10911
10912 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10913 }"
10914 )
10915
10916 (define_insn "*cond_move_not"
10917 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10918 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10919 [(match_operand 3 "cc_register" "") (const_int 0)])
10920 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10921 (not:SI
10922 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10923 "TARGET_ARM"
10924 "@
10925 mvn%D4\\t%0, %2
10926 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10927 [(set_attr "conds" "use")
10928 (set_attr "type" "mvn_reg,multiple")
10929 (set_attr "length" "4,8")]
10930 )
10931
10932 ;; The next two patterns occur when an AND operation is followed by a
10933 ;; scc insn sequence
10934
10935 (define_insn "*sign_extract_onebit"
10936 [(set (match_operand:SI 0 "s_register_operand" "=r")
10937 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10938 (const_int 1)
10939 (match_operand:SI 2 "const_int_operand" "n")))
10940 (clobber (reg:CC CC_REGNUM))]
10941 "TARGET_ARM"
10942 "*
10943 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10944 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10945 return \"mvnne\\t%0, #0\";
10946 "
10947 [(set_attr "conds" "clob")
10948 (set_attr "length" "8")
10949 (set_attr "type" "multiple")]
10950 )
10951
10952 (define_insn "*not_signextract_onebit"
10953 [(set (match_operand:SI 0 "s_register_operand" "=r")
10954 (not:SI
10955 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10956 (const_int 1)
10957 (match_operand:SI 2 "const_int_operand" "n"))))
10958 (clobber (reg:CC CC_REGNUM))]
10959 "TARGET_ARM"
10960 "*
10961 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10962 output_asm_insn (\"tst\\t%1, %2\", operands);
10963 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10964 return \"movne\\t%0, #0\";
10965 "
10966 [(set_attr "conds" "clob")
10967 (set_attr "length" "12")
10968 (set_attr "type" "multiple")]
10969 )
10970 ;; ??? The above patterns need auditing for Thumb-2
10971
10972 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10973 ;; expressions. For simplicity, the first register is also in the unspec
10974 ;; part.
10975 ;; To avoid the usage of GNU extension, the length attribute is computed
10976 ;; in a C function arm_attr_length_push_multi.
10977 (define_insn "*push_multi"
10978 [(match_parallel 2 "multi_register_push"
10979 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10980 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10981 UNSPEC_PUSH_MULT))])]
10982 ""
10983 "*
10984 {
10985 int num_saves = XVECLEN (operands[2], 0);
10986
10987 /* For the StrongARM at least it is faster to
10988 use STR to store only a single register.
10989 In Thumb mode always use push, and the assembler will pick
10990 something appropriate. */
10991 if (num_saves == 1 && TARGET_ARM)
10992 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
10993 else
10994 {
10995 int i;
10996 char pattern[100];
10997
10998 if (TARGET_32BIT)
10999 strcpy (pattern, \"push%?\\t{%1\");
11000 else
11001 strcpy (pattern, \"push\\t{%1\");
11002
11003 for (i = 1; i < num_saves; i++)
11004 {
11005 strcat (pattern, \", %|\");
11006 strcat (pattern,
11007 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
11008 }
11009
11010 strcat (pattern, \"}\");
11011 output_asm_insn (pattern, operands);
11012 }
11013
11014 return \"\";
11015 }"
11016 [(set_attr "type" "store4")
11017 (set (attr "length")
11018 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
11019 )
11020
11021 (define_insn "stack_tie"
11022 [(set (mem:BLK (scratch))
11023 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
11024 (match_operand:SI 1 "s_register_operand" "rk")]
11025 UNSPEC_PRLG_STK))]
11026 ""
11027 ""
11028 [(set_attr "length" "0")
11029 (set_attr "type" "block")]
11030 )
11031
11032 ;; Pop (as used in epilogue RTL)
11033 ;;
11034 (define_insn "*load_multiple_with_writeback"
11035 [(match_parallel 0 "load_multiple_operation"
11036 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11037 (plus:SI (match_dup 1)
11038 (match_operand:SI 2 "const_int_I_operand" "I")))
11039 (set (match_operand:SI 3 "s_register_operand" "=rk")
11040 (mem:SI (match_dup 1)))
11041 ])]
11042 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11043 "*
11044 {
11045 arm_output_multireg_pop (operands, /*return_pc=*/false,
11046 /*cond=*/const_true_rtx,
11047 /*reverse=*/false,
11048 /*update=*/true);
11049 return \"\";
11050 }
11051 "
11052 [(set_attr "type" "load4")
11053 (set_attr "predicable" "yes")
11054 (set (attr "length")
11055 (symbol_ref "arm_attr_length_pop_multi (operands,
11056 /*return_pc=*/false,
11057 /*write_back_p=*/true)"))]
11058 )
11059
11060 ;; Pop with return (as used in epilogue RTL)
11061 ;;
11062 ;; This instruction is generated when the registers are popped at the end of
11063 ;; epilogue. Here, instead of popping the value into LR and then generating
11064 ;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
11065 ;; with (return).
11066 (define_insn "*pop_multiple_with_writeback_and_return"
11067 [(match_parallel 0 "pop_multiple_return"
11068 [(return)
11069 (set (match_operand:SI 1 "s_register_operand" "+rk")
11070 (plus:SI (match_dup 1)
11071 (match_operand:SI 2 "const_int_I_operand" "I")))
11072 (set (match_operand:SI 3 "s_register_operand" "=rk")
11073 (mem:SI (match_dup 1)))
11074 ])]
11075 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11076 "*
11077 {
11078 arm_output_multireg_pop (operands, /*return_pc=*/true,
11079 /*cond=*/const_true_rtx,
11080 /*reverse=*/false,
11081 /*update=*/true);
11082 return \"\";
11083 }
11084 "
11085 [(set_attr "type" "load4")
11086 (set_attr "predicable" "yes")
11087 (set (attr "length")
11088 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11089 /*write_back_p=*/true)"))]
11090 )
11091
11092 (define_insn "*pop_multiple_with_return"
11093 [(match_parallel 0 "pop_multiple_return"
11094 [(return)
11095 (set (match_operand:SI 2 "s_register_operand" "=rk")
11096 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11097 ])]
11098 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11099 "*
11100 {
11101 arm_output_multireg_pop (operands, /*return_pc=*/true,
11102 /*cond=*/const_true_rtx,
11103 /*reverse=*/false,
11104 /*update=*/false);
11105 return \"\";
11106 }
11107 "
11108 [(set_attr "type" "load4")
11109 (set_attr "predicable" "yes")
11110 (set (attr "length")
11111 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
11112 /*write_back_p=*/false)"))]
11113 )
11114
11115 ;; Load into PC and return
11116 (define_insn "*ldr_with_return"
11117 [(return)
11118 (set (reg:SI PC_REGNUM)
11119 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
11120 "TARGET_32BIT && (reload_in_progress || reload_completed)"
11121 "ldr%?\t%|pc, [%0], #4"
11122 [(set_attr "type" "load1")
11123 (set_attr "predicable" "yes")]
11124 )
11125 ;; Pop for floating point registers (as used in epilogue RTL)
11126 (define_insn "*vfp_pop_multiple_with_writeback"
11127 [(match_parallel 0 "pop_multiple_fp"
11128 [(set (match_operand:SI 1 "s_register_operand" "+rk")
11129 (plus:SI (match_dup 1)
11130 (match_operand:SI 2 "const_int_I_operand" "I")))
11131 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
11132 (mem:DF (match_dup 1)))])]
11133 "TARGET_32BIT && TARGET_HARD_FLOAT"
11134 "*
11135 {
11136 int num_regs = XVECLEN (operands[0], 0);
11137 char pattern[100];
11138 rtx op_list[2];
11139 strcpy (pattern, \"vldm\\t\");
11140 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
11141 strcat (pattern, \"!, {\");
11142 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
11143 strcat (pattern, \"%P0\");
11144 if ((num_regs - 1) > 1)
11145 {
11146 strcat (pattern, \"-%P1\");
11147 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
11148 }
11149
11150 strcat (pattern, \"}\");
11151 output_asm_insn (pattern, op_list);
11152 return \"\";
11153 }
11154 "
11155 [(set_attr "type" "load4")
11156 (set_attr "conds" "unconditional")
11157 (set_attr "predicable" "no")]
11158 )
11159
11160 ;; Special patterns for dealing with the constant pool
11161
11162 (define_insn "align_4"
11163 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
11164 "TARGET_EITHER"
11165 "*
11166 assemble_align (32);
11167 return \"\";
11168 "
11169 [(set_attr "type" "no_insn")]
11170 )
11171
11172 (define_insn "align_8"
11173 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
11174 "TARGET_EITHER"
11175 "*
11176 assemble_align (64);
11177 return \"\";
11178 "
11179 [(set_attr "type" "no_insn")]
11180 )
11181
11182 (define_insn "consttable_end"
11183 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
11184 "TARGET_EITHER"
11185 "*
11186 making_const_table = FALSE;
11187 return \"\";
11188 "
11189 [(set_attr "type" "no_insn")]
11190 )
11191
11192 (define_insn "consttable_1"
11193 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
11194 "TARGET_EITHER"
11195 "*
11196 making_const_table = TRUE;
11197 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
11198 assemble_zeros (3);
11199 return \"\";
11200 "
11201 [(set_attr "length" "4")
11202 (set_attr "type" "no_insn")]
11203 )
11204
11205 (define_insn "consttable_2"
11206 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
11207 "TARGET_EITHER"
11208 "*
11209 {
11210 rtx x = operands[0];
11211 making_const_table = TRUE;
11212 switch (GET_MODE_CLASS (GET_MODE (x)))
11213 {
11214 case MODE_FLOAT:
11215 arm_emit_fp16_const (x);
11216 break;
11217 default:
11218 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
11219 assemble_zeros (2);
11220 break;
11221 }
11222 return \"\";
11223 }"
11224 [(set_attr "length" "4")
11225 (set_attr "type" "no_insn")]
11226 )
11227
11228 (define_insn "consttable_4"
11229 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
11230 "TARGET_EITHER"
11231 "*
11232 {
11233 rtx x = operands[0];
11234 making_const_table = TRUE;
11235 switch (GET_MODE_CLASS (GET_MODE (x)))
11236 {
11237 case MODE_FLOAT:
11238 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
11239 BITS_PER_WORD);
11240 break;
11241 default:
11242 /* XXX: Sometimes gcc does something really dumb and ends up with
11243 a HIGH in a constant pool entry, usually because it's trying to
11244 load into a VFP register. We know this will always be used in
11245 combination with a LO_SUM which ignores the high bits, so just
11246 strip off the HIGH. */
11247 if (GET_CODE (x) == HIGH)
11248 x = XEXP (x, 0);
11249 assemble_integer (x, 4, BITS_PER_WORD, 1);
11250 mark_symbol_refs_as_used (x);
11251 break;
11252 }
11253 return \"\";
11254 }"
11255 [(set_attr "length" "4")
11256 (set_attr "type" "no_insn")]
11257 )
11258
11259 (define_insn "consttable_8"
11260 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11261 "TARGET_EITHER"
11262 "*
11263 {
11264 making_const_table = TRUE;
11265 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11266 {
11267 case MODE_FLOAT:
11268 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11269 GET_MODE (operands[0]), BITS_PER_WORD);
11270 break;
11271 default:
11272 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11273 break;
11274 }
11275 return \"\";
11276 }"
11277 [(set_attr "length" "8")
11278 (set_attr "type" "no_insn")]
11279 )
11280
11281 (define_insn "consttable_16"
11282 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11283 "TARGET_EITHER"
11284 "*
11285 {
11286 making_const_table = TRUE;
11287 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11288 {
11289 case MODE_FLOAT:
11290 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11291 GET_MODE (operands[0]), BITS_PER_WORD);
11292 break;
11293 default:
11294 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11295 break;
11296 }
11297 return \"\";
11298 }"
11299 [(set_attr "length" "16")
11300 (set_attr "type" "no_insn")]
11301 )
11302
11303 ;; V5 Instructions,
11304
11305 (define_insn "clzsi2"
11306 [(set (match_operand:SI 0 "s_register_operand" "=r")
11307 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11308 "TARGET_32BIT && arm_arch5"
11309 "clz%?\\t%0, %1"
11310 [(set_attr "predicable" "yes")
11311 (set_attr "predicable_short_it" "no")
11312 (set_attr "type" "clz")])
11313
11314 (define_insn "rbitsi2"
11315 [(set (match_operand:SI 0 "s_register_operand" "=r")
11316 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11317 "TARGET_32BIT && arm_arch_thumb2"
11318 "rbit%?\\t%0, %1"
11319 [(set_attr "predicable" "yes")
11320 (set_attr "predicable_short_it" "no")
11321 (set_attr "type" "clz")])
11322
11323 ;; Keep this as a CTZ expression until after reload and then split
11324 ;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11325 ;; to fold with any other expression.
11326
11327 (define_insn_and_split "ctzsi2"
11328 [(set (match_operand:SI 0 "s_register_operand" "=r")
11329 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11330 "TARGET_32BIT && arm_arch_thumb2"
11331 "#"
11332 "&& reload_completed"
11333 [(const_int 0)]
11334 "
11335 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11336 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11337 DONE;
11338 ")
11339
11340 ;; V5E instructions.
11341
11342 (define_insn "prefetch"
11343 [(prefetch (match_operand:SI 0 "address_operand" "p")
11344 (match_operand:SI 1 "" "")
11345 (match_operand:SI 2 "" ""))]
11346 "TARGET_32BIT && arm_arch5e"
11347 "pld\\t%a0"
11348 [(set_attr "type" "load1")]
11349 )
11350
11351 ;; General predication pattern
11352
11353 (define_cond_exec
11354 [(match_operator 0 "arm_comparison_operator"
11355 [(match_operand 1 "cc_register" "")
11356 (const_int 0)])]
11357 "TARGET_32BIT
11358 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
11359 ""
11360 [(set_attr "predicated" "yes")]
11361 )
11362
11363 (define_insn "force_register_use"
11364 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
11365 ""
11366 "%@ %0 needed"
11367 [(set_attr "length" "0")
11368 (set_attr "type" "no_insn")]
11369 )
11370
11371
11372 ;; Patterns for exception handling
11373
11374 (define_expand "eh_return"
11375 [(use (match_operand 0 "general_operand" ""))]
11376 "TARGET_EITHER"
11377 "
11378 {
11379 if (TARGET_32BIT)
11380 emit_insn (gen_arm_eh_return (operands[0]));
11381 else
11382 emit_insn (gen_thumb_eh_return (operands[0]));
11383 DONE;
11384 }"
11385 )
11386
11387 ;; We can't expand this before we know where the link register is stored.
11388 (define_insn_and_split "arm_eh_return"
11389 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11390 VUNSPEC_EH_RETURN)
11391 (clobber (match_scratch:SI 1 "=&r"))]
11392 "TARGET_ARM"
11393 "#"
11394 "&& reload_completed"
11395 [(const_int 0)]
11396 "
11397 {
11398 arm_set_return_address (operands[0], operands[1]);
11399 DONE;
11400 }"
11401 )
11402
11403 \f
11404 ;; TLS support
11405
11406 (define_insn "load_tp_hard"
11407 [(set (match_operand:SI 0 "register_operand" "=r")
11408 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11409 "TARGET_HARD_TP"
11410 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11411 [(set_attr "predicable" "yes")
11412 (set_attr "type" "mrs")]
11413 )
11414
11415 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11416 (define_insn "load_tp_soft"
11417 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11418 (clobber (reg:SI LR_REGNUM))
11419 (clobber (reg:SI IP_REGNUM))
11420 (clobber (reg:CC CC_REGNUM))]
11421 "TARGET_SOFT_TP"
11422 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11423 [(set_attr "conds" "clob")
11424 (set_attr "type" "branch")]
11425 )
11426
11427 ;; tls descriptor call
11428 (define_insn "tlscall"
11429 [(set (reg:SI R0_REGNUM)
11430 (unspec:SI [(reg:SI R0_REGNUM)
11431 (match_operand:SI 0 "" "X")
11432 (match_operand 1 "" "")] UNSPEC_TLS))
11433 (clobber (reg:SI R1_REGNUM))
11434 (clobber (reg:SI LR_REGNUM))
11435 (clobber (reg:SI CC_REGNUM))]
11436 "TARGET_GNU2_TLS"
11437 {
11438 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11439 INTVAL (operands[1]));
11440 return "bl\\t%c0(tlscall)";
11441 }
11442 [(set_attr "conds" "clob")
11443 (set_attr "length" "4")
11444 (set_attr "type" "branch")]
11445 )
11446
11447 ;; For thread pointer builtin
11448 (define_expand "get_thread_pointersi"
11449 [(match_operand:SI 0 "s_register_operand" "=r")]
11450 ""
11451 "
11452 {
11453 arm_load_tp (operands[0]);
11454 DONE;
11455 }")
11456
11457 ;;
11458
11459 ;; We only care about the lower 16 bits of the constant
11460 ;; being inserted into the upper 16 bits of the register.
11461 (define_insn "*arm_movtas_ze"
11462 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
11463 (const_int 16)
11464 (const_int 16))
11465 (match_operand:SI 1 "const_int_operand" ""))]
11466 "TARGET_HAVE_MOVT"
11467 "@
11468 movt%?\t%0, %L1
11469 movt\t%0, %L1"
11470 [(set_attr "arch" "32,v8mb")
11471 (set_attr "predicable" "yes")
11472 (set_attr "predicable_short_it" "no")
11473 (set_attr "length" "4")
11474 (set_attr "type" "alu_sreg")]
11475 )
11476
11477 (define_insn "*arm_rev"
11478 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11479 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11480 "arm_arch6"
11481 "@
11482 rev\t%0, %1
11483 rev%?\t%0, %1
11484 rev%?\t%0, %1"
11485 [(set_attr "arch" "t1,t2,32")
11486 (set_attr "length" "2,2,4")
11487 (set_attr "predicable" "no,yes,yes")
11488 (set_attr "predicable_short_it" "no")
11489 (set_attr "type" "rev")]
11490 )
11491
11492 (define_expand "arm_legacy_rev"
11493 [(set (match_operand:SI 2 "s_register_operand" "")
11494 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11495 (const_int 16))
11496 (match_dup 1)))
11497 (set (match_dup 2)
11498 (lshiftrt:SI (match_dup 2)
11499 (const_int 8)))
11500 (set (match_operand:SI 3 "s_register_operand" "")
11501 (rotatert:SI (match_dup 1)
11502 (const_int 8)))
11503 (set (match_dup 2)
11504 (and:SI (match_dup 2)
11505 (const_int -65281)))
11506 (set (match_operand:SI 0 "s_register_operand" "")
11507 (xor:SI (match_dup 3)
11508 (match_dup 2)))]
11509 "TARGET_32BIT"
11510 ""
11511 )
11512
11513 ;; Reuse temporaries to keep register pressure down.
11514 (define_expand "thumb_legacy_rev"
11515 [(set (match_operand:SI 2 "s_register_operand" "")
11516 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11517 (const_int 24)))
11518 (set (match_operand:SI 3 "s_register_operand" "")
11519 (lshiftrt:SI (match_dup 1)
11520 (const_int 24)))
11521 (set (match_dup 3)
11522 (ior:SI (match_dup 3)
11523 (match_dup 2)))
11524 (set (match_operand:SI 4 "s_register_operand" "")
11525 (const_int 16))
11526 (set (match_operand:SI 5 "s_register_operand" "")
11527 (rotatert:SI (match_dup 1)
11528 (match_dup 4)))
11529 (set (match_dup 2)
11530 (ashift:SI (match_dup 5)
11531 (const_int 24)))
11532 (set (match_dup 5)
11533 (lshiftrt:SI (match_dup 5)
11534 (const_int 24)))
11535 (set (match_dup 5)
11536 (ior:SI (match_dup 5)
11537 (match_dup 2)))
11538 (set (match_dup 5)
11539 (rotatert:SI (match_dup 5)
11540 (match_dup 4)))
11541 (set (match_operand:SI 0 "s_register_operand" "")
11542 (ior:SI (match_dup 5)
11543 (match_dup 3)))]
11544 "TARGET_THUMB"
11545 ""
11546 )
11547
11548 ;; ARM-specific expansion of signed mod by power of 2
11549 ;; using conditional negate.
11550 ;; For r0 % n where n is a power of 2 produce:
11551 ;; rsbs r1, r0, #0
11552 ;; and r0, r0, #(n - 1)
11553 ;; and r1, r1, #(n - 1)
11554 ;; rsbpl r0, r1, #0
11555
11556 (define_expand "modsi3"
11557 [(match_operand:SI 0 "register_operand" "")
11558 (match_operand:SI 1 "register_operand" "")
11559 (match_operand:SI 2 "const_int_operand" "")]
11560 "TARGET_32BIT"
11561 {
11562 HOST_WIDE_INT val = INTVAL (operands[2]);
11563
11564 if (val <= 0
11565 || exact_log2 (val) <= 0)
11566 FAIL;
11567
11568 rtx mask = GEN_INT (val - 1);
11569
11570 /* In the special case of x0 % 2 we can do the even shorter:
11571 cmp r0, #0
11572 and r0, r0, #1
11573 rsblt r0, r0, #0. */
11574
11575 if (val == 2)
11576 {
11577 rtx cc_reg = arm_gen_compare_reg (LT,
11578 operands[1], const0_rtx, NULL_RTX);
11579 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11580 rtx masked = gen_reg_rtx (SImode);
11581
11582 emit_insn (gen_andsi3 (masked, operands[1], mask));
11583 emit_move_insn (operands[0],
11584 gen_rtx_IF_THEN_ELSE (SImode, cond,
11585 gen_rtx_NEG (SImode,
11586 masked),
11587 masked));
11588 DONE;
11589 }
11590
11591 rtx neg_op = gen_reg_rtx (SImode);
11592 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11593 operands[1]));
11594
11595 /* Extract the condition register and mode. */
11596 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11597 rtx cc_reg = SET_DEST (cmp);
11598 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11599
11600 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11601
11602 rtx masked_neg = gen_reg_rtx (SImode);
11603 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11604
11605 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11606 during expand does not always work. Do an IF_THEN_ELSE instead. */
11607 emit_move_insn (operands[0],
11608 gen_rtx_IF_THEN_ELSE (SImode, cond,
11609 gen_rtx_NEG (SImode, masked_neg),
11610 operands[0]));
11611
11612
11613 DONE;
11614 }
11615 )
11616
11617 (define_expand "bswapsi2"
11618 [(set (match_operand:SI 0 "s_register_operand" "=r")
11619 (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11620 "TARGET_EITHER && (arm_arch6 || !optimize_size)"
11621 "
11622 if (!arm_arch6)
11623 {
11624 rtx op2 = gen_reg_rtx (SImode);
11625 rtx op3 = gen_reg_rtx (SImode);
11626
11627 if (TARGET_THUMB)
11628 {
11629 rtx op4 = gen_reg_rtx (SImode);
11630 rtx op5 = gen_reg_rtx (SImode);
11631
11632 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11633 op2, op3, op4, op5));
11634 }
11635 else
11636 {
11637 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11638 op2, op3));
11639 }
11640
11641 DONE;
11642 }
11643 "
11644 )
11645
11646 ;; bswap16 patterns: use revsh and rev16 instructions for the signed
11647 ;; and unsigned variants, respectively. For rev16, expose
11648 ;; byte-swapping in the lower 16 bits only.
11649 (define_insn "*arm_revsh"
11650 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11651 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11652 "arm_arch6"
11653 "@
11654 revsh\t%0, %1
11655 revsh%?\t%0, %1
11656 revsh%?\t%0, %1"
11657 [(set_attr "arch" "t1,t2,32")
11658 (set_attr "length" "2,2,4")
11659 (set_attr "type" "rev")]
11660 )
11661
11662 (define_insn "*arm_rev16"
11663 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11664 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11665 "arm_arch6"
11666 "@
11667 rev16\t%0, %1
11668 rev16%?\t%0, %1
11669 rev16%?\t%0, %1"
11670 [(set_attr "arch" "t1,t2,32")
11671 (set_attr "length" "2,2,4")
11672 (set_attr "type" "rev")]
11673 )
11674
11675 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11676 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
11677 ;; each valid permutation.
11678
11679 (define_insn "arm_rev16si2"
11680 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11681 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11682 (const_int 8))
11683 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11684 (and:SI (lshiftrt:SI (match_dup 1)
11685 (const_int 8))
11686 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11687 "arm_arch6
11688 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11689 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11690 "rev16\\t%0, %1"
11691 [(set_attr "arch" "t1,t2,32")
11692 (set_attr "length" "2,2,4")
11693 (set_attr "type" "rev")]
11694 )
11695
11696 (define_insn "arm_rev16si2_alt"
11697 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11698 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11699 (const_int 8))
11700 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11701 (and:SI (ashift:SI (match_dup 1)
11702 (const_int 8))
11703 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11704 "arm_arch6
11705 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11706 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11707 "rev16\\t%0, %1"
11708 [(set_attr "arch" "t1,t2,32")
11709 (set_attr "length" "2,2,4")
11710 (set_attr "type" "rev")]
11711 )
11712
11713 (define_expand "bswaphi2"
11714 [(set (match_operand:HI 0 "s_register_operand" "=r")
11715 (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11716 "arm_arch6"
11717 ""
11718 )
11719
11720 ;; Patterns for LDRD/STRD in Thumb2 mode
11721
11722 (define_insn "*thumb2_ldrd"
11723 [(set (match_operand:SI 0 "s_register_operand" "=r")
11724 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11725 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11726 (set (match_operand:SI 3 "s_register_operand" "=r")
11727 (mem:SI (plus:SI (match_dup 1)
11728 (match_operand:SI 4 "const_int_operand" ""))))]
11729 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11730 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11731 && (operands_ok_ldrd_strd (operands[0], operands[3],
11732 operands[1], INTVAL (operands[2]),
11733 false, true))"
11734 "ldrd%?\t%0, %3, [%1, %2]"
11735 [(set_attr "type" "load2")
11736 (set_attr "predicable" "yes")
11737 (set_attr "predicable_short_it" "no")])
11738
11739 (define_insn "*thumb2_ldrd_base"
11740 [(set (match_operand:SI 0 "s_register_operand" "=r")
11741 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11742 (set (match_operand:SI 2 "s_register_operand" "=r")
11743 (mem:SI (plus:SI (match_dup 1)
11744 (const_int 4))))]
11745 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11746 && (operands_ok_ldrd_strd (operands[0], operands[2],
11747 operands[1], 0, false, true))"
11748 "ldrd%?\t%0, %2, [%1]"
11749 [(set_attr "type" "load2")
11750 (set_attr "predicable" "yes")
11751 (set_attr "predicable_short_it" "no")])
11752
11753 (define_insn "*thumb2_ldrd_base_neg"
11754 [(set (match_operand:SI 0 "s_register_operand" "=r")
11755 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11756 (const_int -4))))
11757 (set (match_operand:SI 2 "s_register_operand" "=r")
11758 (mem:SI (match_dup 1)))]
11759 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11760 && (operands_ok_ldrd_strd (operands[0], operands[2],
11761 operands[1], -4, false, true))"
11762 "ldrd%?\t%0, %2, [%1, #-4]"
11763 [(set_attr "type" "load2")
11764 (set_attr "predicable" "yes")
11765 (set_attr "predicable_short_it" "no")])
11766
11767 (define_insn "*thumb2_strd"
11768 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11769 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11770 (match_operand:SI 2 "s_register_operand" "r"))
11771 (set (mem:SI (plus:SI (match_dup 0)
11772 (match_operand:SI 3 "const_int_operand" "")))
11773 (match_operand:SI 4 "s_register_operand" "r"))]
11774 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11775 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11776 && (operands_ok_ldrd_strd (operands[2], operands[4],
11777 operands[0], INTVAL (operands[1]),
11778 false, false))"
11779 "strd%?\t%2, %4, [%0, %1]"
11780 [(set_attr "type" "store2")
11781 (set_attr "predicable" "yes")
11782 (set_attr "predicable_short_it" "no")])
11783
11784 (define_insn "*thumb2_strd_base"
11785 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11786 (match_operand:SI 1 "s_register_operand" "r"))
11787 (set (mem:SI (plus:SI (match_dup 0)
11788 (const_int 4)))
11789 (match_operand:SI 2 "s_register_operand" "r"))]
11790 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11791 && (operands_ok_ldrd_strd (operands[1], operands[2],
11792 operands[0], 0, false, false))"
11793 "strd%?\t%1, %2, [%0]"
11794 [(set_attr "type" "store2")
11795 (set_attr "predicable" "yes")
11796 (set_attr "predicable_short_it" "no")])
11797
11798 (define_insn "*thumb2_strd_base_neg"
11799 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11800 (const_int -4)))
11801 (match_operand:SI 1 "s_register_operand" "r"))
11802 (set (mem:SI (match_dup 0))
11803 (match_operand:SI 2 "s_register_operand" "r"))]
11804 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11805 && (operands_ok_ldrd_strd (operands[1], operands[2],
11806 operands[0], -4, false, false))"
11807 "strd%?\t%1, %2, [%0, #-4]"
11808 [(set_attr "type" "store2")
11809 (set_attr "predicable" "yes")
11810 (set_attr "predicable_short_it" "no")])
11811
11812 ;; ARMv8 CRC32 instructions.
11813 (define_insn "<crc_variant>"
11814 [(set (match_operand:SI 0 "s_register_operand" "=r")
11815 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11816 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11817 CRC))]
11818 "TARGET_CRC32"
11819 "<crc_variant>\\t%0, %1, %2"
11820 [(set_attr "type" "crc")
11821 (set_attr "conds" "unconditional")]
11822 )
11823
11824 ;; Load the load/store double peephole optimizations.
11825 (include "ldrdstrd.md")
11826
11827 ;; Load the load/store multiple patterns
11828 (include "ldmstm.md")
11829
11830 ;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11831 ;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11832 ;; The operands are validated through the load_multiple_operation
11833 ;; match_parallel predicate rather than through constraints so enable it only
11834 ;; after reload.
11835 (define_insn "*load_multiple"
11836 [(match_parallel 0 "load_multiple_operation"
11837 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11838 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11839 ])]
11840 "TARGET_32BIT && reload_completed"
11841 "*
11842 {
11843 arm_output_multireg_pop (operands, /*return_pc=*/false,
11844 /*cond=*/const_true_rtx,
11845 /*reverse=*/false,
11846 /*update=*/false);
11847 return \"\";
11848 }
11849 "
11850 [(set_attr "predicable" "yes")]
11851 )
11852
11853 (define_expand "copysignsf3"
11854 [(match_operand:SF 0 "register_operand")
11855 (match_operand:SF 1 "register_operand")
11856 (match_operand:SF 2 "register_operand")]
11857 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11858 "{
11859 emit_move_insn (operands[0], operands[2]);
11860 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11861 GEN_INT (31), GEN_INT (0),
11862 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11863 DONE;
11864 }"
11865 )
11866
11867 (define_expand "copysigndf3"
11868 [(match_operand:DF 0 "register_operand")
11869 (match_operand:DF 1 "register_operand")
11870 (match_operand:DF 2 "register_operand")]
11871 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11872 "{
11873 rtx op0_low = gen_lowpart (SImode, operands[0]);
11874 rtx op0_high = gen_highpart (SImode, operands[0]);
11875 rtx op1_low = gen_lowpart (SImode, operands[1]);
11876 rtx op1_high = gen_highpart (SImode, operands[1]);
11877 rtx op2_high = gen_highpart (SImode, operands[2]);
11878
11879 rtx scratch1 = gen_reg_rtx (SImode);
11880 rtx scratch2 = gen_reg_rtx (SImode);
11881 emit_move_insn (scratch1, op2_high);
11882 emit_move_insn (scratch2, op1_high);
11883
11884 emit_insn(gen_rtx_SET(scratch1,
11885 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11886 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11887 emit_move_insn (op0_low, op1_low);
11888 emit_move_insn (op0_high, scratch2);
11889
11890 DONE;
11891 }"
11892 )
11893
11894 ;; movmisalign patterns for HImode and SImode.
11895 (define_expand "movmisalign<mode>"
11896 [(match_operand:HSI 0 "general_operand")
11897 (match_operand:HSI 1 "general_operand")]
11898 "unaligned_access"
11899 {
11900 /* This pattern is not permitted to fail during expansion: if both arguments
11901 are non-registers (e.g. memory := constant), force operand 1 into a
11902 register. */
11903 rtx (* gen_unaligned_load)(rtx, rtx);
11904 rtx tmp_dest = operands[0];
11905 if (!s_register_operand (operands[0], <MODE>mode)
11906 && !s_register_operand (operands[1], <MODE>mode))
11907 operands[1] = force_reg (<MODE>mode, operands[1]);
11908
11909 if (<MODE>mode == HImode)
11910 {
11911 gen_unaligned_load = gen_unaligned_loadhiu;
11912 tmp_dest = gen_reg_rtx (SImode);
11913 }
11914 else
11915 gen_unaligned_load = gen_unaligned_loadsi;
11916
11917 if (MEM_P (operands[1]))
11918 {
11919 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11920 if (<MODE>mode == HImode)
11921 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11922 }
11923 else
11924 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11925
11926 DONE;
11927 })
11928
11929 (define_insn "<cdp>"
11930 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11931 (match_operand:SI 1 "immediate_operand" "n")
11932 (match_operand:SI 2 "immediate_operand" "n")
11933 (match_operand:SI 3 "immediate_operand" "n")
11934 (match_operand:SI 4 "immediate_operand" "n")
11935 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11936 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11937 {
11938 arm_const_bounds (operands[0], 0, 16);
11939 arm_const_bounds (operands[1], 0, 16);
11940 arm_const_bounds (operands[2], 0, (1 << 5));
11941 arm_const_bounds (operands[3], 0, (1 << 5));
11942 arm_const_bounds (operands[4], 0, (1 << 5));
11943 arm_const_bounds (operands[5], 0, 8);
11944 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11945 }
11946 [(set_attr "length" "4")
11947 (set_attr "type" "coproc")])
11948
11949 (define_insn "*ldc"
11950 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11951 (match_operand:SI 1 "immediate_operand" "n")
11952 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11953 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11954 {
11955 arm_const_bounds (operands[0], 0, 16);
11956 arm_const_bounds (operands[1], 0, (1 << 5));
11957 return "<ldc>\\tp%c0, CR%c1, %2";
11958 }
11959 [(set_attr "length" "4")
11960 (set_attr "type" "coproc")])
11961
11962 (define_insn "*stc"
11963 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11964 (match_operand:SI 1 "immediate_operand" "n")
11965 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11966 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11967 {
11968 arm_const_bounds (operands[0], 0, 16);
11969 arm_const_bounds (operands[1], 0, (1 << 5));
11970 return "<stc>\\tp%c0, CR%c1, %2";
11971 }
11972 [(set_attr "length" "4")
11973 (set_attr "type" "coproc")])
11974
11975 (define_expand "<ldc>"
11976 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11977 (match_operand:SI 1 "immediate_operand")
11978 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11979 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11980
11981 (define_expand "<stc>"
11982 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11983 (match_operand:SI 1 "immediate_operand")
11984 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11985 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11986
11987 (define_insn "<mcr>"
11988 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11989 (match_operand:SI 1 "immediate_operand" "n")
11990 (match_operand:SI 2 "s_register_operand" "r")
11991 (match_operand:SI 3 "immediate_operand" "n")
11992 (match_operand:SI 4 "immediate_operand" "n")
11993 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11994 (use (match_dup 2))]
11995 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11996 {
11997 arm_const_bounds (operands[0], 0, 16);
11998 arm_const_bounds (operands[1], 0, 8);
11999 arm_const_bounds (operands[3], 0, (1 << 5));
12000 arm_const_bounds (operands[4], 0, (1 << 5));
12001 arm_const_bounds (operands[5], 0, 8);
12002 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
12003 }
12004 [(set_attr "length" "4")
12005 (set_attr "type" "coproc")])
12006
12007 (define_insn "<mrc>"
12008 [(set (match_operand:SI 0 "s_register_operand" "=r")
12009 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
12010 (match_operand:SI 2 "immediate_operand" "n")
12011 (match_operand:SI 3 "immediate_operand" "n")
12012 (match_operand:SI 4 "immediate_operand" "n")
12013 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
12014 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
12015 {
12016 arm_const_bounds (operands[1], 0, 16);
12017 arm_const_bounds (operands[2], 0, 8);
12018 arm_const_bounds (operands[3], 0, (1 << 5));
12019 arm_const_bounds (operands[4], 0, (1 << 5));
12020 arm_const_bounds (operands[5], 0, 8);
12021 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
12022 }
12023 [(set_attr "length" "4")
12024 (set_attr "type" "coproc")])
12025
12026 (define_insn "<mcrr>"
12027 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
12028 (match_operand:SI 1 "immediate_operand" "n")
12029 (match_operand:DI 2 "s_register_operand" "r")
12030 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
12031 (use (match_dup 2))]
12032 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
12033 {
12034 arm_const_bounds (operands[0], 0, 16);
12035 arm_const_bounds (operands[1], 0, 8);
12036 arm_const_bounds (operands[3], 0, (1 << 5));
12037 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
12038 }
12039 [(set_attr "length" "4")
12040 (set_attr "type" "coproc")])
12041
12042 (define_insn "<mrrc>"
12043 [(set (match_operand:DI 0 "s_register_operand" "=r")
12044 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
12045 (match_operand:SI 2 "immediate_operand" "n")
12046 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
12047 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
12048 {
12049 arm_const_bounds (operands[1], 0, 16);
12050 arm_const_bounds (operands[2], 0, 8);
12051 arm_const_bounds (operands[3], 0, (1 << 5));
12052 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
12053 }
12054 [(set_attr "length" "4")
12055 (set_attr "type" "coproc")])
12056
12057 ;; Vector bits common to IWMMXT and Neon
12058 (include "vec-common.md")
12059 ;; Load the Intel Wireless Multimedia Extension patterns
12060 (include "iwmmxt.md")
12061 ;; Load the VFP co-processor patterns
12062 (include "vfp.md")
12063 ;; Thumb-1 patterns
12064 (include "thumb1.md")
12065 ;; Thumb-2 patterns
12066 (include "thumb2.md")
12067 ;; Neon patterns
12068 (include "neon.md")
12069 ;; Crypto patterns
12070 (include "crypto.md")
12071 ;; Synchronization Primitives
12072 (include "sync.md")
12073 ;; Fixed-point patterns
12074 (include "arm-fixed.md")