]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/arm.md
[arm] Implement DImode SIMD32 intrinsics
[thirdparty/gcc.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright (C) 1991-2019 Free Software Foundation, Inc.
3 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;; and Martin Simmons (@harleqn.co.uk).
5 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
6
7 ;; This file is part of GCC.
8
9 ;; GCC is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published
11 ;; by the Free Software Foundation; either version 3, or (at your
12 ;; option) any later version.
13
14 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
15 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 ;; License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3. If not see
21 ;; <http://www.gnu.org/licenses/>.
22
23 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24
25 \f
26 ;;---------------------------------------------------------------------------
27 ;; Constants
28
29 ;; Register numbers -- All machine registers should be defined here
30 (define_constants
31 [(R0_REGNUM 0) ; First CORE register
32 (R1_REGNUM 1) ; Second CORE register
33 (R4_REGNUM 4) ; Fifth CORE register
34 (FDPIC_REGNUM 9) ; FDPIC register
35 (IP_REGNUM 12) ; Scratch register
36 (SP_REGNUM 13) ; Stack pointer
37 (LR_REGNUM 14) ; Return address register
38 (PC_REGNUM 15) ; Program counter
39 (LAST_ARM_REGNUM 15) ;
40 (CC_REGNUM 100) ; Condition code pseudo register
41 (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
42 ]
43 )
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46 [(DOM_CC_X_AND_Y 0)
47 (DOM_CC_NX_OR_Y 1)
48 (DOM_CC_X_OR_Y 2)
49 ]
50 )
51 ;; conditional compare combination
52 (define_constants
53 [(CMP_CMP 0)
54 (CMN_CMP 1)
55 (CMP_CMN 2)
56 (CMN_CMN 3)
57 (NUM_OF_COND_CMP 4)
58 ]
59 )
60
61 \f
62 ;;---------------------------------------------------------------------------
63 ;; Attributes
64
65 ;; Processor type. This is created automatically from arm-cores.def.
66 (include "arm-tune.md")
67
68 ;; Instruction classification types
69 (include "types.md")
70
71 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
72 ; generating ARM code. This is used to control the length of some insn
73 ; patterns that share the same RTL in both ARM and Thumb code.
74 (define_attr "is_thumb" "yes,no"
75 (const (if_then_else (symbol_ref "TARGET_THUMB")
76 (const_string "yes") (const_string "no"))))
77
78 ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
79 (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
80
81 ; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
82 (define_attr "is_thumb1" "yes,no"
83 (const (if_then_else (symbol_ref "TARGET_THUMB1")
84 (const_string "yes") (const_string "no"))))
85
86 ; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
87 ; The arm_restrict_it flag enables the "short IT" feature which
88 ; restricts IT blocks to a single 16-bit instruction.
89 ; This attribute should only be used on 16-bit Thumb-2 instructions
90 ; which may be predicated (the "predicable" attribute must be set).
91 (define_attr "predicable_short_it" "no,yes" (const_string "no"))
92
93 ; Mark an instruction as suitable for "short IT" blocks in Thumb-2.
94 ; This attribute should only be used on instructions which may emit
95 ; an IT block in their expansion which is not a short IT.
96 (define_attr "enabled_for_short_it" "no,yes" (const_string "yes"))
97
98 ;; Operand number of an input operand that is shifted. Zero if the
99 ;; given instruction does not shift one of its input operands.
100 (define_attr "shift" "" (const_int 0))
101
102 ;; [For compatibility with AArch64 in pipeline models]
103 ;; Attribute that specifies whether or not the instruction touches fp
104 ;; registers.
105 (define_attr "fp" "no,yes" (const_string "no"))
106
107 ; Floating Point Unit. If we only have floating point emulation, then there
108 ; is no point in scheduling the floating point insns. (Well, for best
109 ; performance we should try and group them together).
110 (define_attr "fpu" "none,vfp"
111 (const (symbol_ref "arm_fpu_attr")))
112
113 ; Predicated means that the insn form is conditionally executed based on a
114 ; predicate. We default to 'no' because no Thumb patterns match this rule
115 ; and not all ARM insns do.
116 (define_attr "predicated" "yes,no" (const_string "no"))
117
118 ; LENGTH of an instruction (in bytes)
119 (define_attr "length" ""
120 (const_int 4))
121
122 ; The architecture which supports the instruction (or alternative).
123 ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
124 ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
125 ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
126 ; arm_arch6. "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
127 ; Baseline. This attribute is used to compute attribute "enabled",
128 ; use type "any" to enable an alternative in all cases.
129 (define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
130 (const_string "any"))
131
132 (define_attr "arch_enabled" "no,yes"
133 (cond [(eq_attr "arch" "any")
134 (const_string "yes")
135
136 (and (eq_attr "arch" "a")
137 (match_test "TARGET_ARM"))
138 (const_string "yes")
139
140 (and (eq_attr "arch" "t")
141 (match_test "TARGET_THUMB"))
142 (const_string "yes")
143
144 (and (eq_attr "arch" "t1")
145 (match_test "TARGET_THUMB1"))
146 (const_string "yes")
147
148 (and (eq_attr "arch" "t2")
149 (match_test "TARGET_THUMB2"))
150 (const_string "yes")
151
152 (and (eq_attr "arch" "32")
153 (match_test "TARGET_32BIT"))
154 (const_string "yes")
155
156 (and (eq_attr "arch" "v6")
157 (match_test "TARGET_32BIT && arm_arch6"))
158 (const_string "yes")
159
160 (and (eq_attr "arch" "nov6")
161 (match_test "TARGET_32BIT && !arm_arch6"))
162 (const_string "yes")
163
164 (and (eq_attr "arch" "v6t2")
165 (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
166 (const_string "yes")
167
168 (and (eq_attr "arch" "v8mb")
169 (match_test "TARGET_THUMB1 && arm_arch8"))
170 (const_string "yes")
171
172 (and (eq_attr "arch" "iwmmxt2")
173 (match_test "TARGET_REALLY_IWMMXT2"))
174 (const_string "yes")
175
176 (and (eq_attr "arch" "armv6_or_vfpv3")
177 (match_test "arm_arch6 || TARGET_VFP3"))
178 (const_string "yes")
179
180 (and (eq_attr "arch" "neon")
181 (match_test "TARGET_NEON"))
182 (const_string "yes")
183 ]
184
185 (const_string "no")))
186
187 (define_attr "opt" "any,speed,size"
188 (const_string "any"))
189
190 (define_attr "opt_enabled" "no,yes"
191 (cond [(eq_attr "opt" "any")
192 (const_string "yes")
193
194 (and (eq_attr "opt" "speed")
195 (match_test "optimize_function_for_speed_p (cfun)"))
196 (const_string "yes")
197
198 (and (eq_attr "opt" "size")
199 (match_test "optimize_function_for_size_p (cfun)"))
200 (const_string "yes")]
201 (const_string "no")))
202
203 (define_attr "use_literal_pool" "no,yes"
204 (cond [(and (eq_attr "type" "f_loads,f_loadd")
205 (match_test "CONSTANT_P (operands[1])"))
206 (const_string "yes")]
207 (const_string "no")))
208
209 ; Enable all alternatives that are both arch_enabled and insn_enabled.
210 ; FIXME:: opt_enabled has been temporarily removed till the time we have
211 ; an attribute that allows the use of such alternatives.
212 ; This depends on caching of speed_p, size_p on a per
213 ; alternative basis. The problem is that the enabled attribute
214 ; cannot depend on any state that is not cached or is not constant
215 ; for a compilation unit. We probably need a generic "hot/cold"
216 ; alternative which if implemented can help with this. We disable this
217 ; until such a time as this is implemented and / or the improvements or
218 ; regressions with removing this attribute are double checked.
219 ; See ashldi3_neon and <shift>di3_neon in neon.md.
220
221 (define_attr "enabled" "no,yes"
222 (cond [(and (eq_attr "predicable_short_it" "no")
223 (and (eq_attr "predicated" "yes")
224 (match_test "arm_restrict_it")))
225 (const_string "no")
226
227 (and (eq_attr "enabled_for_short_it" "no")
228 (match_test "arm_restrict_it"))
229 (const_string "no")
230
231 (eq_attr "arch_enabled" "no")
232 (const_string "no")]
233 (const_string "yes")))
234
235 ; POOL_RANGE is how far away from a constant pool entry that this insn
236 ; can be placed. If the distance is zero, then this insn will never
237 ; reference the pool.
238 ; Note that for Thumb constant pools the PC value is rounded down to the
239 ; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
240 ; Thumb insns) should be set to <max_range> - 2.
241 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
242 ; before its address. It is set to <max_range> - (8 + <data_size>).
243 (define_attr "arm_pool_range" "" (const_int 0))
244 (define_attr "thumb2_pool_range" "" (const_int 0))
245 (define_attr "arm_neg_pool_range" "" (const_int 0))
246 (define_attr "thumb2_neg_pool_range" "" (const_int 0))
247
248 (define_attr "pool_range" ""
249 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
250 (attr "arm_pool_range")))
251 (define_attr "neg_pool_range" ""
252 (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
253 (attr "arm_neg_pool_range")))
254
255 ; An assembler sequence may clobber the condition codes without us knowing.
256 ; If such an insn references the pool, then we have no way of knowing how,
257 ; so use the most conservative value for pool_range.
258 (define_asm_attributes
259 [(set_attr "conds" "clob")
260 (set_attr "length" "4")
261 (set_attr "pool_range" "250")])
262
263 ; Load scheduling, set from the arm_ld_sched variable
264 ; initialized by arm_option_override()
265 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
266
267 ; condition codes: this one is used by final_prescan_insn to speed up
268 ; conditionalizing instructions. It saves having to scan the rtl to see if
269 ; it uses or alters the condition codes.
270 ;
271 ; USE means that the condition codes are used by the insn in the process of
272 ; outputting code, this means (at present) that we can't use the insn in
273 ; inlined branches
274 ;
275 ; SET means that the purpose of the insn is to set the condition codes in a
276 ; well defined manner.
277 ;
278 ; CLOB means that the condition codes are altered in an undefined manner, if
279 ; they are altered at all
280 ;
281 ; UNCONDITIONAL means the instruction cannot be conditionally executed and
282 ; that the instruction does not use or alter the condition codes.
283 ;
284 ; NOCOND means that the instruction does not use or alter the condition
285 ; codes but can be converted into a conditionally exectuted instruction.
286
287 (define_attr "conds" "use,set,clob,unconditional,nocond"
288 (if_then_else
289 (ior (eq_attr "is_thumb1" "yes")
290 (eq_attr "type" "call"))
291 (const_string "clob")
292 (if_then_else (eq_attr "is_neon_type" "no")
293 (const_string "nocond")
294 (const_string "unconditional"))))
295
296 ; Predicable means that the insn can be conditionally executed based on
297 ; an automatically added predicate (additional patterns are generated by
298 ; gen...). We default to 'no' because no Thumb patterns match this rule
299 ; and not all ARM patterns do.
300 (define_attr "predicable" "no,yes" (const_string "no"))
301
302 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
303 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
304 ; suffer blockages enough to warrant modelling this (and it can adversely
305 ; affect the schedule).
306 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
307
308 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
309 ; to stall the processor. Used with model_wbuf above.
310 (define_attr "write_conflict" "no,yes"
311 (if_then_else (eq_attr "type"
312 "block,call,load_4")
313 (const_string "yes")
314 (const_string "no")))
315
316 ; Classify the insns into those that take one cycle and those that take more
317 ; than one on the main cpu execution unit.
318 (define_attr "core_cycles" "single,multi"
319 (if_then_else (eq_attr "type"
320 "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
321 alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
322 alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
323 logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
324 logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
325 wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
326 wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
327 wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
328 wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
329 wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
330 wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
331 wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
332 wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
333 wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
334 wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
335 wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
336 (const_string "single")
337 (const_string "multi")))
338
339 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
340 ;; distant label. Only applicable to Thumb code.
341 (define_attr "far_jump" "yes,no" (const_string "no"))
342
343
344 ;; The number of machine instructions this pattern expands to.
345 ;; Used for Thumb-2 conditional execution.
346 (define_attr "ce_count" "" (const_int 1))
347
348 ;;---------------------------------------------------------------------------
349 ;; Unspecs
350
351 (include "unspecs.md")
352
353 ;;---------------------------------------------------------------------------
354 ;; Mode iterators
355
356 (include "iterators.md")
357
358 ;;---------------------------------------------------------------------------
359 ;; Predicates
360
361 (include "predicates.md")
362 (include "constraints.md")
363
364 ;;---------------------------------------------------------------------------
365 ;; Pipeline descriptions
366
367 (define_attr "tune_cortexr4" "yes,no"
368 (const (if_then_else
369 (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
370 (const_string "yes")
371 (const_string "no"))))
372
373 ;; True if the generic scheduling description should be used.
374
375 (define_attr "generic_sched" "yes,no"
376 (const (if_then_else
377 (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
378 arm926ejs,arm10e,arm1026ejs,arm1136js,\
379 arm1136jfs,cortexa5,cortexa7,cortexa8,\
380 cortexa9,cortexa12,cortexa15,cortexa17,\
381 cortexa53,cortexa57,cortexm4,cortexm7,\
382 exynosm1,marvell_pj4,xgene1")
383 (eq_attr "tune_cortexr4" "yes"))
384 (const_string "no")
385 (const_string "yes"))))
386
387 (define_attr "generic_vfp" "yes,no"
388 (const (if_then_else
389 (and (eq_attr "fpu" "vfp")
390 (eq_attr "tune" "!arm10e,cortexa5,cortexa7,\
391 cortexa8,cortexa9,cortexa53,cortexm4,\
392 cortexm7,marvell_pj4,xgene1")
393 (eq_attr "tune_cortexr4" "no"))
394 (const_string "yes")
395 (const_string "no"))))
396
397 (include "marvell-f-iwmmxt.md")
398 (include "arm-generic.md")
399 (include "arm926ejs.md")
400 (include "arm1020e.md")
401 (include "arm1026ejs.md")
402 (include "arm1136jfs.md")
403 (include "fa526.md")
404 (include "fa606te.md")
405 (include "fa626te.md")
406 (include "fmp626.md")
407 (include "fa726te.md")
408 (include "cortex-a5.md")
409 (include "cortex-a7.md")
410 (include "cortex-a8.md")
411 (include "cortex-a9.md")
412 (include "cortex-a15.md")
413 (include "cortex-a17.md")
414 (include "cortex-a53.md")
415 (include "cortex-a57.md")
416 (include "cortex-r4.md")
417 (include "cortex-r4f.md")
418 (include "cortex-m7.md")
419 (include "cortex-m4.md")
420 (include "cortex-m4-fpu.md")
421 (include "exynos-m1.md")
422 (include "vfp11.md")
423 (include "marvell-pj4.md")
424 (include "xgene1.md")
425
426 \f
427 ;;---------------------------------------------------------------------------
428 ;; Insn patterns
429 ;;
430 ;; Addition insns.
431
432 ;; Note: For DImode insns, there is normally no reason why operands should
433 ;; not be in the same register, what we don't want is for something being
434 ;; written to partially overlap something that is an input.
435
436 (define_expand "adddi3"
437 [(parallel
438 [(set (match_operand:DI 0 "s_register_operand")
439 (plus:DI (match_operand:DI 1 "s_register_operand")
440 (match_operand:DI 2 "arm_adddi_operand")))
441 (clobber (reg:CC CC_REGNUM))])]
442 "TARGET_EITHER"
443 "
444 if (TARGET_THUMB1 && !REG_P (operands[2]))
445 operands[2] = force_reg (DImode, operands[2]);
446 "
447 )
448
449 (define_insn_and_split "*arm_adddi3"
450 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r,&r,&r")
451 (plus:DI (match_operand:DI 1 "arm_general_register_operand" "%0, 0, r, 0, r")
452 (match_operand:DI 2 "arm_general_adddi_operand" "r, 0, r, Dd, Dd")))
453 (clobber (reg:CC CC_REGNUM))]
454 "TARGET_32BIT"
455 "#"
456 "TARGET_32BIT"
457 [(parallel [(set (reg:CC_C CC_REGNUM)
458 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
459 (match_dup 1)))
460 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
461 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
462 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
463 "
464 {
465 operands[3] = gen_highpart (SImode, operands[0]);
466 operands[0] = gen_lowpart (SImode, operands[0]);
467 operands[4] = gen_highpart (SImode, operands[1]);
468 operands[1] = gen_lowpart (SImode, operands[1]);
469 operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
470 operands[2] = gen_lowpart (SImode, operands[2]);
471 }"
472 [(set_attr "conds" "clob")
473 (set_attr "length" "8")
474 (set_attr "type" "multiple")]
475 )
476
477 (define_insn_and_split "*adddi_sesidi_di"
478 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
479 (plus:DI (sign_extend:DI
480 (match_operand:SI 2 "s_register_operand" "r,r"))
481 (match_operand:DI 1 "s_register_operand" "0,r")))
482 (clobber (reg:CC CC_REGNUM))]
483 "TARGET_32BIT"
484 "#"
485 "TARGET_32BIT && reload_completed"
486 [(parallel [(set (reg:CC_C CC_REGNUM)
487 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
488 (match_dup 1)))
489 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
490 (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
491 (const_int 31))
492 (match_dup 4))
493 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
494 "
495 {
496 operands[3] = gen_highpart (SImode, operands[0]);
497 operands[0] = gen_lowpart (SImode, operands[0]);
498 operands[4] = gen_highpart (SImode, operands[1]);
499 operands[1] = gen_lowpart (SImode, operands[1]);
500 operands[2] = gen_lowpart (SImode, operands[2]);
501 }"
502 [(set_attr "conds" "clob")
503 (set_attr "length" "8")
504 (set_attr "type" "multiple")]
505 )
506
507 (define_insn_and_split "*adddi_zesidi_di"
508 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
509 (plus:DI (zero_extend:DI
510 (match_operand:SI 2 "s_register_operand" "r,r"))
511 (match_operand:DI 1 "s_register_operand" "0,r")))
512 (clobber (reg:CC CC_REGNUM))]
513 "TARGET_32BIT"
514 "#"
515 "TARGET_32BIT && reload_completed"
516 [(parallel [(set (reg:CC_C CC_REGNUM)
517 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
518 (match_dup 1)))
519 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
520 (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
521 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
522 "
523 {
524 operands[3] = gen_highpart (SImode, operands[0]);
525 operands[0] = gen_lowpart (SImode, operands[0]);
526 operands[4] = gen_highpart (SImode, operands[1]);
527 operands[1] = gen_lowpart (SImode, operands[1]);
528 operands[2] = gen_lowpart (SImode, operands[2]);
529 }"
530 [(set_attr "conds" "clob")
531 (set_attr "length" "8")
532 (set_attr "type" "multiple")]
533 )
534
535 (define_expand "addv<mode>4"
536 [(match_operand:SIDI 0 "register_operand")
537 (match_operand:SIDI 1 "register_operand")
538 (match_operand:SIDI 2 "register_operand")
539 (match_operand 3 "")]
540 "TARGET_32BIT"
541 {
542 emit_insn (gen_add<mode>3_compareV (operands[0], operands[1], operands[2]));
543 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[3]);
544
545 DONE;
546 })
547
548 (define_expand "uaddv<mode>4"
549 [(match_operand:SIDI 0 "register_operand")
550 (match_operand:SIDI 1 "register_operand")
551 (match_operand:SIDI 2 "register_operand")
552 (match_operand 3 "")]
553 "TARGET_32BIT"
554 {
555 emit_insn (gen_add<mode>3_compareC (operands[0], operands[1], operands[2]));
556 arm_gen_unlikely_cbranch (NE, CC_Cmode, operands[3]);
557
558 DONE;
559 })
560
561 (define_expand "addsi3"
562 [(set (match_operand:SI 0 "s_register_operand")
563 (plus:SI (match_operand:SI 1 "s_register_operand")
564 (match_operand:SI 2 "reg_or_int_operand")))]
565 "TARGET_EITHER"
566 "
567 if (TARGET_32BIT && CONST_INT_P (operands[2]))
568 {
569 arm_split_constant (PLUS, SImode, NULL_RTX,
570 INTVAL (operands[2]), operands[0], operands[1],
571 optimize && can_create_pseudo_p ());
572 DONE;
573 }
574 "
575 )
576
577 ; If there is a scratch available, this will be faster than synthesizing the
578 ; addition.
579 (define_peephole2
580 [(match_scratch:SI 3 "r")
581 (set (match_operand:SI 0 "arm_general_register_operand" "")
582 (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
583 (match_operand:SI 2 "const_int_operand" "")))]
584 "TARGET_32BIT &&
585 !(const_ok_for_arm (INTVAL (operands[2]))
586 || const_ok_for_arm (-INTVAL (operands[2])))
587 && const_ok_for_arm (~INTVAL (operands[2]))"
588 [(set (match_dup 3) (match_dup 2))
589 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
590 ""
591 )
592
593 ;; The r/r/k alternative is required when reloading the address
594 ;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
595 ;; put the duplicated register first, and not try the commutative version.
596 (define_insn_and_split "*arm_addsi3"
597 [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
598 (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")
599 (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
600 "TARGET_32BIT"
601 "@
602 add%?\\t%0, %0, %2
603 add%?\\t%0, %1, %2
604 add%?\\t%0, %1, %2
605 add%?\\t%0, %1, %2
606 add%?\\t%0, %1, %2
607 add%?\\t%0, %1, %2
608 add%?\\t%0, %2, %1
609 add%?\\t%0, %1, %2
610 addw%?\\t%0, %1, %2
611 addw%?\\t%0, %1, %2
612 sub%?\\t%0, %1, #%n2
613 sub%?\\t%0, %1, #%n2
614 sub%?\\t%0, %1, #%n2
615 subw%?\\t%0, %1, #%n2
616 subw%?\\t%0, %1, #%n2
617 #"
618 "TARGET_32BIT
619 && CONST_INT_P (operands[2])
620 && !const_ok_for_op (INTVAL (operands[2]), PLUS)
621 && (reload_completed || !arm_eliminable_register (operands[1]))"
622 [(clobber (const_int 0))]
623 "
624 arm_split_constant (PLUS, SImode, curr_insn,
625 INTVAL (operands[2]), operands[0],
626 operands[1], 0);
627 DONE;
628 "
629 [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
630 (set_attr "predicable" "yes")
631 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
632 (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
633 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
634 (const_string "alu_imm")
635 (const_string "alu_sreg")))
636 ]
637 )
638
639 (define_insn_and_split "adddi3_compareV"
640 [(set (reg:CC_V CC_REGNUM)
641 (ne:CC_V
642 (plus:TI
643 (sign_extend:TI (match_operand:DI 1 "register_operand" "r"))
644 (sign_extend:TI (match_operand:DI 2 "register_operand" "r")))
645 (sign_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
646 (set (match_operand:DI 0 "register_operand" "=&r")
647 (plus:DI (match_dup 1) (match_dup 2)))]
648 "TARGET_32BIT"
649 "#"
650 "&& reload_completed"
651 [(parallel [(set (reg:CC_C CC_REGNUM)
652 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
653 (match_dup 1)))
654 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
655 (parallel [(set (reg:CC_V CC_REGNUM)
656 (ne:CC_V
657 (plus:DI (plus:DI
658 (sign_extend:DI (match_dup 4))
659 (sign_extend:DI (match_dup 5)))
660 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
661 (plus:DI (sign_extend:DI
662 (plus:SI (match_dup 4) (match_dup 5)))
663 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
664 (set (match_dup 3) (plus:SI (plus:SI
665 (match_dup 4) (match_dup 5))
666 (ltu:SI (reg:CC_C CC_REGNUM)
667 (const_int 0))))])]
668 "
669 {
670 operands[3] = gen_highpart (SImode, operands[0]);
671 operands[0] = gen_lowpart (SImode, operands[0]);
672 operands[4] = gen_highpart (SImode, operands[1]);
673 operands[1] = gen_lowpart (SImode, operands[1]);
674 operands[5] = gen_highpart (SImode, operands[2]);
675 operands[2] = gen_lowpart (SImode, operands[2]);
676 }"
677 [(set_attr "conds" "set")
678 (set_attr "length" "8")
679 (set_attr "type" "multiple")]
680 )
681
682 (define_insn "addsi3_compareV"
683 [(set (reg:CC_V CC_REGNUM)
684 (ne:CC_V
685 (plus:DI
686 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
687 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
688 (sign_extend:DI (plus:SI (match_dup 1) (match_dup 2)))))
689 (set (match_operand:SI 0 "register_operand" "=r")
690 (plus:SI (match_dup 1) (match_dup 2)))]
691 "TARGET_32BIT"
692 "adds%?\\t%0, %1, %2"
693 [(set_attr "conds" "set")
694 (set_attr "type" "alus_sreg")]
695 )
696
697 (define_insn "*addsi3_compareV_upper"
698 [(set (reg:CC_V CC_REGNUM)
699 (ne:CC_V
700 (plus:DI
701 (plus:DI
702 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
703 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
704 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
705 (plus:DI (sign_extend:DI
706 (plus:SI (match_dup 1) (match_dup 2)))
707 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
708 (set (match_operand:SI 0 "register_operand" "=r")
709 (plus:SI
710 (plus:SI (match_dup 1) (match_dup 2))
711 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
712 "TARGET_32BIT"
713 "adcs%?\\t%0, %1, %2"
714 [(set_attr "conds" "set")
715 (set_attr "type" "adcs_reg")]
716 )
717
718 (define_insn_and_split "adddi3_compareC"
719 [(set (reg:CC_C CC_REGNUM)
720 (ne:CC_C
721 (plus:TI
722 (zero_extend:TI (match_operand:DI 1 "register_operand" "r"))
723 (zero_extend:TI (match_operand:DI 2 "register_operand" "r")))
724 (zero_extend:TI (plus:DI (match_dup 1) (match_dup 2)))))
725 (set (match_operand:DI 0 "register_operand" "=&r")
726 (plus:DI (match_dup 1) (match_dup 2)))]
727 "TARGET_32BIT"
728 "#"
729 "&& reload_completed"
730 [(parallel [(set (reg:CC_C CC_REGNUM)
731 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
732 (match_dup 1)))
733 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
734 (parallel [(set (reg:CC_C CC_REGNUM)
735 (ne:CC_C
736 (plus:DI (plus:DI
737 (zero_extend:DI (match_dup 4))
738 (zero_extend:DI (match_dup 5)))
739 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
740 (plus:DI (zero_extend:DI
741 (plus:SI (match_dup 4) (match_dup 5)))
742 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
743 (set (match_dup 3) (plus:SI
744 (plus:SI (match_dup 4) (match_dup 5))
745 (ltu:SI (reg:CC_C CC_REGNUM)
746 (const_int 0))))])]
747 "
748 {
749 operands[3] = gen_highpart (SImode, operands[0]);
750 operands[0] = gen_lowpart (SImode, operands[0]);
751 operands[4] = gen_highpart (SImode, operands[1]);
752 operands[5] = gen_highpart (SImode, operands[2]);
753 operands[1] = gen_lowpart (SImode, operands[1]);
754 operands[2] = gen_lowpart (SImode, operands[2]);
755 }"
756 [(set_attr "conds" "set")
757 (set_attr "length" "8")
758 (set_attr "type" "multiple")]
759 )
760
761 (define_insn "*addsi3_compareC_upper"
762 [(set (reg:CC_C CC_REGNUM)
763 (ne:CC_C
764 (plus:DI
765 (plus:DI
766 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
767 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
768 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))
769 (plus:DI (zero_extend:DI
770 (plus:SI (match_dup 1) (match_dup 2)))
771 (ltu:DI (reg:CC_C CC_REGNUM) (const_int 0)))))
772 (set (match_operand:SI 0 "register_operand" "=r")
773 (plus:SI
774 (plus:SI (match_dup 1) (match_dup 2))
775 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
776 "TARGET_32BIT"
777 "adcs%?\\t%0, %1, %2"
778 [(set_attr "conds" "set")
779 (set_attr "type" "adcs_reg")]
780 )
781
782 (define_insn "addsi3_compareC"
783 [(set (reg:CC_C CC_REGNUM)
784 (ne:CC_C
785 (plus:DI
786 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
787 (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
788 (zero_extend:DI
789 (plus:SI (match_dup 1) (match_dup 2)))))
790 (set (match_operand:SI 0 "register_operand" "=r")
791 (plus:SI (match_dup 1) (match_dup 2)))]
792 "TARGET_32BIT"
793 "adds%?\\t%0, %1, %2"
794 [(set_attr "conds" "set")
795 (set_attr "type" "alus_sreg")]
796 )
797
798 (define_insn "addsi3_compare0"
799 [(set (reg:CC_NOOV CC_REGNUM)
800 (compare:CC_NOOV
801 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
802 (match_operand:SI 2 "arm_add_operand" "I,L,r"))
803 (const_int 0)))
804 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
805 (plus:SI (match_dup 1) (match_dup 2)))]
806 "TARGET_ARM"
807 "@
808 adds%?\\t%0, %1, %2
809 subs%?\\t%0, %1, #%n2
810 adds%?\\t%0, %1, %2"
811 [(set_attr "conds" "set")
812 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
813 )
814
815 (define_insn "*addsi3_compare0_scratch"
816 [(set (reg:CC_NOOV CC_REGNUM)
817 (compare:CC_NOOV
818 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
819 (match_operand:SI 1 "arm_add_operand" "I,L, r"))
820 (const_int 0)))]
821 "TARGET_ARM"
822 "@
823 cmn%?\\t%0, %1
824 cmp%?\\t%0, #%n1
825 cmn%?\\t%0, %1"
826 [(set_attr "conds" "set")
827 (set_attr "predicable" "yes")
828 (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
829 )
830
831 (define_insn "*compare_negsi_si"
832 [(set (reg:CC_Z CC_REGNUM)
833 (compare:CC_Z
834 (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
835 (match_operand:SI 1 "s_register_operand" "l,r")))]
836 "TARGET_32BIT"
837 "cmn%?\\t%1, %0"
838 [(set_attr "conds" "set")
839 (set_attr "predicable" "yes")
840 (set_attr "arch" "t2,*")
841 (set_attr "length" "2,4")
842 (set_attr "predicable_short_it" "yes,no")
843 (set_attr "type" "alus_sreg")]
844 )
845
846 ;; This is the canonicalization of subsi3_compare when the
847 ;; addend is a constant.
848 (define_insn "cmpsi2_addneg"
849 [(set (reg:CC CC_REGNUM)
850 (compare:CC
851 (match_operand:SI 1 "s_register_operand" "r,r")
852 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
853 (set (match_operand:SI 0 "s_register_operand" "=r,r")
854 (plus:SI (match_dup 1)
855 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
856 "TARGET_32BIT
857 && (INTVAL (operands[2])
858 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
859 {
860 /* For 0 and INT_MIN it is essential that we use subs, as adds will result
861 in different condition codes (like cmn rather than like cmp), so that
862 alternative comes first. Both alternatives can match for any 0x??000000
863 where except for 0 and INT_MIN it doesn't matter what we choose, and also
864 for -1 and 1 with TARGET_THUMB2, in that case prefer instruction with #1
865 as it is shorter. */
866 if (which_alternative == 0 && operands[3] != const1_rtx)
867 return "subs%?\\t%0, %1, #%n3";
868 else
869 return "adds%?\\t%0, %1, %3";
870 }
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" "l,0,l,0,r,r,r")
920 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,I,L,r"))
921 (match_dup 1)))
922 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r,r")
923 (plus:SI (match_dup 1) (match_dup 2)))]
924 "TARGET_32BIT"
925 "@
926 adds%?\\t%0, %1, %2
927 adds%?\\t%0, %0, %2
928 subs%?\\t%0, %1, #%n2
929 subs%?\\t%0, %0, #%n2
930 adds%?\\t%0, %1, %2
931 subs%?\\t%0, %1, #%n2
932 adds%?\\t%0, %1, %2"
933 [(set_attr "conds" "set")
934 (set_attr "arch" "t2,t2,t2,t2,*,*,*")
935 (set_attr "length" "2,2,2,2,4,4,4")
936 (set_attr "type"
937 "alus_sreg,alus_imm,alus_sreg,alus_imm,alus_imm,alus_imm,alus_sreg")]
938 )
939
940 (define_insn "*addsi3_compare_op2"
941 [(set (reg:CC_C CC_REGNUM)
942 (compare:CC_C
943 (plus:SI (match_operand:SI 1 "s_register_operand" "l,0,l,0,r,r,r")
944 (match_operand:SI 2 "arm_add_operand" "lPd,Py,lPx,Pw,I,L,r"))
945 (match_dup 2)))
946 (set (match_operand:SI 0 "s_register_operand" "=l,l,l,l,r,r,r")
947 (plus:SI (match_dup 1) (match_dup 2)))]
948 "TARGET_32BIT"
949 "@
950 adds%?\\t%0, %1, %2
951 adds%?\\t%0, %0, %2
952 subs%?\\t%0, %1, #%n2
953 subs%?\\t%0, %0, #%n2
954 adds%?\\t%0, %1, %2
955 subs%?\\t%0, %1, #%n2
956 adds%?\\t%0, %1, %2"
957 [(set_attr "conds" "set")
958 (set_attr "arch" "t2,t2,t2,t2,*,*,*")
959 (set_attr "length" "2,2,2,2,4,4,4")
960 (set_attr "type"
961 "alus_sreg,alus_imm,alus_sreg,alus_imm,alus_imm,alus_imm,alus_sreg")]
962 )
963
964 (define_insn "*compare_addsi2_op0"
965 [(set (reg:CC_C CC_REGNUM)
966 (compare:CC_C
967 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
968 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
969 (match_dup 0)))]
970 "TARGET_32BIT"
971 "@
972 cmp%?\\t%0, #%n1
973 cmn%?\\t%0, %1
974 cmn%?\\t%0, %1
975 cmp%?\\t%0, #%n1
976 cmn%?\\t%0, %1"
977 [(set_attr "conds" "set")
978 (set_attr "predicable" "yes")
979 (set_attr "arch" "t2,t2,*,*,*")
980 (set_attr "predicable_short_it" "yes,yes,no,no,no")
981 (set_attr "length" "2,2,4,4,4")
982 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
983 )
984
985 (define_insn "*compare_addsi2_op1"
986 [(set (reg:CC_C CC_REGNUM)
987 (compare:CC_C
988 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
989 (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
990 (match_dup 1)))]
991 "TARGET_32BIT"
992 "@
993 cmp%?\\t%0, #%n1
994 cmn%?\\t%0, %1
995 cmn%?\\t%0, %1
996 cmp%?\\t%0, #%n1
997 cmn%?\\t%0, %1"
998 [(set_attr "conds" "set")
999 (set_attr "predicable" "yes")
1000 (set_attr "arch" "t2,t2,*,*,*")
1001 (set_attr "predicable_short_it" "yes,yes,no,no,no")
1002 (set_attr "length" "2,2,4,4,4")
1003 (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
1004 )
1005
1006 (define_insn "*addsi3_carryin_<optab>"
1007 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1008 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
1009 (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
1010 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1011 "TARGET_32BIT"
1012 "@
1013 adc%?\\t%0, %1, %2
1014 adc%?\\t%0, %1, %2
1015 sbc%?\\t%0, %1, #%B2"
1016 [(set_attr "conds" "use")
1017 (set_attr "predicable" "yes")
1018 (set_attr "arch" "t2,*,*")
1019 (set_attr "length" "4")
1020 (set_attr "predicable_short_it" "yes,no,no")
1021 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1022 )
1023
1024 (define_insn "*addsi3_carryin_alt2_<optab>"
1025 [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
1026 (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
1027 (match_operand:SI 1 "s_register_operand" "%l,r,r"))
1028 (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
1029 "TARGET_32BIT"
1030 "@
1031 adc%?\\t%0, %1, %2
1032 adc%?\\t%0, %1, %2
1033 sbc%?\\t%0, %1, #%B2"
1034 [(set_attr "conds" "use")
1035 (set_attr "predicable" "yes")
1036 (set_attr "arch" "t2,*,*")
1037 (set_attr "length" "4")
1038 (set_attr "predicable_short_it" "yes,no,no")
1039 (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1040 )
1041
1042 (define_insn "*addsi3_carryin_shift_<optab>"
1043 [(set (match_operand:SI 0 "s_register_operand" "=r")
1044 (plus:SI (plus:SI
1045 (match_operator:SI 2 "shift_operator"
1046 [(match_operand:SI 3 "s_register_operand" "r")
1047 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1048 (match_operand:SI 1 "s_register_operand" "r"))
1049 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1050 "TARGET_32BIT"
1051 "adc%?\\t%0, %1, %3%S2"
1052 [(set_attr "conds" "use")
1053 (set_attr "predicable" "yes")
1054 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1055 (const_string "alu_shift_imm")
1056 (const_string "alu_shift_reg")))]
1057 )
1058
1059 (define_insn "*addsi3_carryin_clobercc_<optab>"
1060 [(set (match_operand:SI 0 "s_register_operand" "=r")
1061 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1062 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1063 (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
1064 (clobber (reg:CC CC_REGNUM))]
1065 "TARGET_32BIT"
1066 "adcs%?\\t%0, %1, %2"
1067 [(set_attr "conds" "set")
1068 (set_attr "type" "adcs_reg")]
1069 )
1070
1071 (define_expand "subv<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 (NE, CC_Vmode, operands[3]);
1080
1081 DONE;
1082 })
1083
1084 (define_expand "usubv<mode>4"
1085 [(match_operand:SIDI 0 "register_operand")
1086 (match_operand:SIDI 1 "register_operand")
1087 (match_operand:SIDI 2 "register_operand")
1088 (match_operand 3 "")]
1089 "TARGET_32BIT"
1090 {
1091 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], operands[2]));
1092 arm_gen_unlikely_cbranch (LTU, CCmode, operands[3]);
1093
1094 DONE;
1095 })
1096
1097 (define_insn_and_split "subdi3_compare1"
1098 [(set (reg:CC CC_REGNUM)
1099 (compare:CC
1100 (match_operand:DI 1 "register_operand" "r")
1101 (match_operand:DI 2 "register_operand" "r")))
1102 (set (match_operand:DI 0 "register_operand" "=&r")
1103 (minus:DI (match_dup 1) (match_dup 2)))]
1104 "TARGET_32BIT"
1105 "#"
1106 "&& reload_completed"
1107 [(parallel [(set (reg:CC CC_REGNUM)
1108 (compare:CC (match_dup 1) (match_dup 2)))
1109 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1110 (parallel [(set (reg:CC CC_REGNUM)
1111 (compare:CC (match_dup 4) (match_dup 5)))
1112 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1113 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
1114 {
1115 operands[3] = gen_highpart (SImode, operands[0]);
1116 operands[0] = gen_lowpart (SImode, operands[0]);
1117 operands[4] = gen_highpart (SImode, operands[1]);
1118 operands[1] = gen_lowpart (SImode, operands[1]);
1119 operands[5] = gen_highpart (SImode, operands[2]);
1120 operands[2] = gen_lowpart (SImode, operands[2]);
1121 }
1122 [(set_attr "conds" "set")
1123 (set_attr "length" "8")
1124 (set_attr "type" "multiple")]
1125 )
1126
1127 (define_insn "subsi3_compare1"
1128 [(set (reg:CC CC_REGNUM)
1129 (compare:CC
1130 (match_operand:SI 1 "register_operand" "r")
1131 (match_operand:SI 2 "register_operand" "r")))
1132 (set (match_operand:SI 0 "register_operand" "=r")
1133 (minus:SI (match_dup 1) (match_dup 2)))]
1134 "TARGET_32BIT"
1135 "subs%?\\t%0, %1, %2"
1136 [(set_attr "conds" "set")
1137 (set_attr "type" "alus_sreg")]
1138 )
1139
1140 (define_insn "*subsi3_carryin"
1141 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1142 (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I,Pz")
1143 (match_operand:SI 2 "s_register_operand" "r,r,r"))
1144 (match_operand:SI 3 "arm_borrow_operation" "")))]
1145 "TARGET_32BIT"
1146 "@
1147 sbc%?\\t%0, %1, %2
1148 rsc%?\\t%0, %2, %1
1149 sbc%?\\t%0, %2, %2, lsl #1"
1150 [(set_attr "conds" "use")
1151 (set_attr "arch" "*,a,t2")
1152 (set_attr "predicable" "yes")
1153 (set_attr "type" "adc_reg,adc_imm,alu_shift_imm")]
1154 )
1155
1156 (define_insn "*subsi3_carryin_const"
1157 [(set (match_operand:SI 0 "s_register_operand" "=r")
1158 (minus:SI (plus:SI
1159 (match_operand:SI 1 "s_register_operand" "r")
1160 (match_operand:SI 2 "arm_neg_immediate_operand" "L"))
1161 (match_operand:SI 3 "arm_borrow_operation" "")))]
1162 "TARGET_32BIT"
1163 "sbc\\t%0, %1, #%n2"
1164 [(set_attr "conds" "use")
1165 (set_attr "type" "adc_imm")]
1166 )
1167
1168 (define_insn "*subsi3_carryin_const0"
1169 [(set (match_operand:SI 0 "s_register_operand" "=r")
1170 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
1171 (match_operand:SI 2 "arm_borrow_operation" "")))]
1172 "TARGET_32BIT"
1173 "sbc\\t%0, %1, #0"
1174 [(set_attr "conds" "use")
1175 (set_attr "type" "adc_imm")]
1176 )
1177
1178 (define_insn "*subsi3_carryin_compare"
1179 [(set (reg:CC CC_REGNUM)
1180 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
1181 (match_operand:SI 2 "s_register_operand" "r")))
1182 (set (match_operand:SI 0 "s_register_operand" "=r")
1183 (minus:SI (minus:SI (match_dup 1) (match_dup 2))
1184 (match_operand:SI 3 "arm_borrow_operation" "")))]
1185 "TARGET_32BIT"
1186 "sbcs\\t%0, %1, %2"
1187 [(set_attr "conds" "set")
1188 (set_attr "type" "adcs_reg")]
1189 )
1190
1191 (define_insn "*subsi3_carryin_compare_const"
1192 [(set (reg:CC CC_REGNUM)
1193 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1194 (match_operand:SI 2 "const_int_I_operand" "I")))
1195 (set (match_operand:SI 0 "s_register_operand" "=r")
1196 (minus:SI (plus:SI
1197 (match_dup 1)
1198 (match_operand:SI 3 "arm_neg_immediate_operand" "L"))
1199 (match_operand:SI 4 "arm_borrow_operation" "")))]
1200 "TARGET_32BIT
1201 && (INTVAL (operands[2])
1202 == trunc_int_for_mode (-INTVAL (operands[3]), SImode))"
1203 "sbcs\\t%0, %1, #%n3"
1204 [(set_attr "conds" "set")
1205 (set_attr "type" "adcs_imm")]
1206 )
1207
1208 (define_insn "*subsi3_carryin_compare_const0"
1209 [(set (reg:CC CC_REGNUM)
1210 (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
1211 (const_int 0)))
1212 (set (match_operand:SI 0 "s_register_operand" "=r")
1213 (minus:SI (match_dup 1)
1214 (match_operand:SI 2 "arm_borrow_operation" "")))]
1215 "TARGET_32BIT"
1216 "sbcs\\t%0, %1, #0"
1217 [(set_attr "conds" "set")
1218 (set_attr "type" "adcs_imm")]
1219 )
1220
1221 (define_insn "*subsi3_carryin_shift"
1222 [(set (match_operand:SI 0 "s_register_operand" "=r")
1223 (minus:SI (minus:SI
1224 (match_operand:SI 1 "s_register_operand" "r")
1225 (match_operator:SI 2 "shift_operator"
1226 [(match_operand:SI 3 "s_register_operand" "r")
1227 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
1228 (match_operand:SI 5 "arm_borrow_operation" "")))]
1229 "TARGET_32BIT"
1230 "sbc%?\\t%0, %1, %3%S2"
1231 [(set_attr "conds" "use")
1232 (set_attr "predicable" "yes")
1233 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1234 (const_string "alu_shift_imm")
1235 (const_string "alu_shift_reg")))]
1236 )
1237
1238 (define_insn "*rsbsi3_carryin_shift"
1239 [(set (match_operand:SI 0 "s_register_operand" "=r")
1240 (minus:SI (minus:SI
1241 (match_operator:SI 2 "shift_operator"
1242 [(match_operand:SI 3 "s_register_operand" "r")
1243 (match_operand:SI 4 "reg_or_int_operand" "rM")])
1244 (match_operand:SI 1 "s_register_operand" "r"))
1245 (match_operand:SI 5 "arm_borrow_operation" "")))]
1246 "TARGET_ARM"
1247 "rsc%?\\t%0, %1, %3%S2"
1248 [(set_attr "conds" "use")
1249 (set_attr "predicable" "yes")
1250 (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1251 (const_string "alu_shift_imm")
1252 (const_string "alu_shift_reg")))]
1253 )
1254
1255 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
1256 (define_split
1257 [(set (match_operand:SI 0 "s_register_operand" "")
1258 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1259 (match_operand:SI 2 "s_register_operand" ""))
1260 (const_int -1)))
1261 (clobber (match_operand:SI 3 "s_register_operand" ""))]
1262 "TARGET_32BIT"
1263 [(set (match_dup 3) (match_dup 1))
1264 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1265 "
1266 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1267 ")
1268
1269 (define_expand "addsf3"
1270 [(set (match_operand:SF 0 "s_register_operand")
1271 (plus:SF (match_operand:SF 1 "s_register_operand")
1272 (match_operand:SF 2 "s_register_operand")))]
1273 "TARGET_32BIT && TARGET_HARD_FLOAT"
1274 "
1275 ")
1276
1277 (define_expand "adddf3"
1278 [(set (match_operand:DF 0 "s_register_operand")
1279 (plus:DF (match_operand:DF 1 "s_register_operand")
1280 (match_operand:DF 2 "s_register_operand")))]
1281 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1282 "
1283 ")
1284
1285 (define_expand "subdi3"
1286 [(parallel
1287 [(set (match_operand:DI 0 "s_register_operand")
1288 (minus:DI (match_operand:DI 1 "s_register_operand")
1289 (match_operand:DI 2 "s_register_operand")))
1290 (clobber (reg:CC CC_REGNUM))])]
1291 "TARGET_EITHER"
1292 "
1293 ")
1294
1295 (define_insn_and_split "*arm_subdi3"
1296 [(set (match_operand:DI 0 "arm_general_register_operand" "=&r,&r,&r")
1297 (minus:DI (match_operand:DI 1 "arm_general_register_operand" "0,r,0")
1298 (match_operand:DI 2 "arm_general_register_operand" "r,0,0")))
1299 (clobber (reg:CC CC_REGNUM))]
1300 "TARGET_32BIT"
1301 "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1302 "TARGET_32BIT"
1303 [(parallel [(set (reg:CC CC_REGNUM)
1304 (compare:CC (match_dup 1) (match_dup 2)))
1305 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1306 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1307 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
1308 {
1309 operands[3] = gen_highpart (SImode, operands[0]);
1310 operands[0] = gen_lowpart (SImode, operands[0]);
1311 operands[4] = gen_highpart (SImode, operands[1]);
1312 operands[1] = gen_lowpart (SImode, operands[1]);
1313 operands[5] = gen_highpart (SImode, operands[2]);
1314 operands[2] = gen_lowpart (SImode, operands[2]);
1315 }
1316 [(set_attr "conds" "clob")
1317 (set_attr "length" "8")
1318 (set_attr "type" "multiple")]
1319 )
1320
1321 (define_insn_and_split "*subdi_di_zesidi"
1322 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1323 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1324 (zero_extend:DI
1325 (match_operand:SI 2 "s_register_operand" "r,r"))))
1326 (clobber (reg:CC CC_REGNUM))]
1327 "TARGET_32BIT"
1328 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1329 "&& reload_completed"
1330 [(parallel [(set (reg:CC CC_REGNUM)
1331 (compare:CC (match_dup 1) (match_dup 2)))
1332 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1333 (set (match_dup 3) (minus:SI (match_dup 4)
1334 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
1335 {
1336 operands[3] = gen_highpart (SImode, operands[0]);
1337 operands[0] = gen_lowpart (SImode, operands[0]);
1338 operands[4] = gen_highpart (SImode, operands[1]);
1339 operands[1] = gen_lowpart (SImode, operands[1]);
1340 }
1341 [(set_attr "conds" "clob")
1342 (set_attr "length" "8")
1343 (set_attr "type" "multiple")]
1344 )
1345
1346 (define_insn_and_split "*subdi_di_sesidi"
1347 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1348 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1349 (sign_extend:DI
1350 (match_operand:SI 2 "s_register_operand" "r,r"))))
1351 (clobber (reg:CC CC_REGNUM))]
1352 "TARGET_32BIT"
1353 "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1354 "&& reload_completed"
1355 [(parallel [(set (reg:CC CC_REGNUM)
1356 (compare:CC (match_dup 1) (match_dup 2)))
1357 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1358 (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1359 (ashiftrt:SI (match_dup 2)
1360 (const_int 31)))
1361 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
1362 {
1363 operands[3] = gen_highpart (SImode, operands[0]);
1364 operands[0] = gen_lowpart (SImode, operands[0]);
1365 operands[4] = gen_highpart (SImode, operands[1]);
1366 operands[1] = gen_lowpart (SImode, operands[1]);
1367 }
1368 [(set_attr "conds" "clob")
1369 (set_attr "length" "8")
1370 (set_attr "type" "multiple")]
1371 )
1372
1373 (define_insn_and_split "*subdi_zesidi_di"
1374 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1375 (minus:DI (zero_extend:DI
1376 (match_operand:SI 2 "s_register_operand" "r,r"))
1377 (match_operand:DI 1 "s_register_operand" "0,r")))
1378 (clobber (reg:CC CC_REGNUM))]
1379 "TARGET_ARM"
1380 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1381 ; is equivalent to:
1382 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1383 "&& reload_completed"
1384 [(parallel [(set (reg:CC CC_REGNUM)
1385 (compare:CC (match_dup 2) (match_dup 1)))
1386 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1387 (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1388 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
1389 {
1390 operands[3] = gen_highpart (SImode, operands[0]);
1391 operands[0] = gen_lowpart (SImode, operands[0]);
1392 operands[4] = gen_highpart (SImode, operands[1]);
1393 operands[1] = gen_lowpart (SImode, operands[1]);
1394 }
1395 [(set_attr "conds" "clob")
1396 (set_attr "length" "8")
1397 (set_attr "type" "multiple")]
1398 )
1399
1400 (define_insn_and_split "*subdi_sesidi_di"
1401 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1402 (minus:DI (sign_extend:DI
1403 (match_operand:SI 2 "s_register_operand" "r,r"))
1404 (match_operand:DI 1 "s_register_operand" "0,r")))
1405 (clobber (reg:CC CC_REGNUM))]
1406 "TARGET_ARM"
1407 "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1408 ; is equivalent to:
1409 ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1410 "&& reload_completed"
1411 [(parallel [(set (reg:CC CC_REGNUM)
1412 (compare:CC (match_dup 2) (match_dup 1)))
1413 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1414 (set (match_dup 3) (minus:SI (minus:SI
1415 (ashiftrt:SI (match_dup 2)
1416 (const_int 31))
1417 (match_dup 4))
1418 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
1419 {
1420 operands[3] = gen_highpart (SImode, operands[0]);
1421 operands[0] = gen_lowpart (SImode, operands[0]);
1422 operands[4] = gen_highpart (SImode, operands[1]);
1423 operands[1] = gen_lowpart (SImode, operands[1]);
1424 }
1425 [(set_attr "conds" "clob")
1426 (set_attr "length" "8")
1427 (set_attr "type" "multiple")]
1428 )
1429
1430 (define_insn_and_split "*subdi_zesidi_zesidi"
1431 [(set (match_operand:DI 0 "s_register_operand" "=r")
1432 (minus:DI (zero_extend:DI
1433 (match_operand:SI 1 "s_register_operand" "r"))
1434 (zero_extend:DI
1435 (match_operand:SI 2 "s_register_operand" "r"))))
1436 (clobber (reg:CC CC_REGNUM))]
1437 "TARGET_32BIT"
1438 "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1439 "&& reload_completed"
1440 [(parallel [(set (reg:CC CC_REGNUM)
1441 (compare:CC (match_dup 1) (match_dup 2)))
1442 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1443 (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1444 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
1445 {
1446 operands[3] = gen_highpart (SImode, operands[0]);
1447 operands[0] = gen_lowpart (SImode, operands[0]);
1448 }
1449 [(set_attr "conds" "clob")
1450 (set_attr "length" "8")
1451 (set_attr "type" "multiple")]
1452 )
1453
1454 (define_expand "subsi3"
1455 [(set (match_operand:SI 0 "s_register_operand")
1456 (minus:SI (match_operand:SI 1 "reg_or_int_operand")
1457 (match_operand:SI 2 "s_register_operand")))]
1458 "TARGET_EITHER"
1459 "
1460 if (CONST_INT_P (operands[1]))
1461 {
1462 if (TARGET_32BIT)
1463 {
1464 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
1465 operands[1] = force_reg (SImode, operands[1]);
1466 else
1467 {
1468 arm_split_constant (MINUS, SImode, NULL_RTX,
1469 INTVAL (operands[1]), operands[0],
1470 operands[2],
1471 optimize && can_create_pseudo_p ());
1472 DONE;
1473 }
1474 }
1475 else /* TARGET_THUMB1 */
1476 operands[1] = force_reg (SImode, operands[1]);
1477 }
1478 "
1479 )
1480
1481 ; ??? Check Thumb-2 split length
1482 (define_insn_and_split "*arm_subsi3_insn"
1483 [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
1484 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
1485 (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
1486 "TARGET_32BIT"
1487 "@
1488 sub%?\\t%0, %1, %2
1489 sub%?\\t%0, %2
1490 sub%?\\t%0, %1, %2
1491 rsb%?\\t%0, %2, %1
1492 rsb%?\\t%0, %2, %1
1493 sub%?\\t%0, %1, %2
1494 sub%?\\t%0, %1, %2
1495 sub%?\\t%0, %1, %2
1496 #"
1497 "&& (CONST_INT_P (operands[1])
1498 && !const_ok_for_arm (INTVAL (operands[1])))"
1499 [(clobber (const_int 0))]
1500 "
1501 arm_split_constant (MINUS, SImode, curr_insn,
1502 INTVAL (operands[1]), operands[0], operands[2], 0);
1503 DONE;
1504 "
1505 [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1506 (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
1507 (set_attr "predicable" "yes")
1508 (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
1509 (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
1510 )
1511
1512 (define_peephole2
1513 [(match_scratch:SI 3 "r")
1514 (set (match_operand:SI 0 "arm_general_register_operand" "")
1515 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1516 (match_operand:SI 2 "arm_general_register_operand" "")))]
1517 "TARGET_32BIT
1518 && !const_ok_for_arm (INTVAL (operands[1]))
1519 && const_ok_for_arm (~INTVAL (operands[1]))"
1520 [(set (match_dup 3) (match_dup 1))
1521 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1522 ""
1523 )
1524
1525 (define_insn "subsi3_compare0"
1526 [(set (reg:CC_NOOV CC_REGNUM)
1527 (compare:CC_NOOV
1528 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1529 (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
1530 (const_int 0)))
1531 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1532 (minus:SI (match_dup 1) (match_dup 2)))]
1533 "TARGET_32BIT"
1534 "@
1535 subs%?\\t%0, %1, %2
1536 subs%?\\t%0, %1, %2
1537 rsbs%?\\t%0, %2, %1"
1538 [(set_attr "conds" "set")
1539 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1540 )
1541
1542 (define_insn "subsi3_compare"
1543 [(set (reg:CC CC_REGNUM)
1544 (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1545 (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1546 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1547 (minus:SI (match_dup 1) (match_dup 2)))]
1548 "TARGET_32BIT"
1549 "@
1550 subs%?\\t%0, %1, %2
1551 subs%?\\t%0, %1, %2
1552 rsbs%?\\t%0, %2, %1"
1553 [(set_attr "conds" "set")
1554 (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1555 )
1556
1557 (define_expand "subsf3"
1558 [(set (match_operand:SF 0 "s_register_operand")
1559 (minus:SF (match_operand:SF 1 "s_register_operand")
1560 (match_operand:SF 2 "s_register_operand")))]
1561 "TARGET_32BIT && TARGET_HARD_FLOAT"
1562 "
1563 ")
1564
1565 (define_expand "subdf3"
1566 [(set (match_operand:DF 0 "s_register_operand")
1567 (minus:DF (match_operand:DF 1 "s_register_operand")
1568 (match_operand:DF 2 "s_register_operand")))]
1569 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1570 "
1571 ")
1572
1573 \f
1574 ;; Multiplication insns
1575
1576 (define_expand "mulhi3"
1577 [(set (match_operand:HI 0 "s_register_operand")
1578 (mult:HI (match_operand:HI 1 "s_register_operand")
1579 (match_operand:HI 2 "s_register_operand")))]
1580 "TARGET_DSP_MULTIPLY"
1581 "
1582 {
1583 rtx result = gen_reg_rtx (SImode);
1584 emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1585 emit_move_insn (operands[0], gen_lowpart (HImode, result));
1586 DONE;
1587 }"
1588 )
1589
1590 (define_expand "mulsi3"
1591 [(set (match_operand:SI 0 "s_register_operand")
1592 (mult:SI (match_operand:SI 2 "s_register_operand")
1593 (match_operand:SI 1 "s_register_operand")))]
1594 "TARGET_EITHER"
1595 ""
1596 )
1597
1598 ;; Use `&' and then `0' to prevent operands 0 and 2 being the same
1599 (define_insn "*mul"
1600 [(set (match_operand:SI 0 "s_register_operand" "=l,r,&r,&r")
1601 (mult:SI (match_operand:SI 2 "s_register_operand" "l,r,r,r")
1602 (match_operand:SI 1 "s_register_operand" "%0,r,0,r")))]
1603 "TARGET_32BIT"
1604 "mul%?\\t%0, %2, %1"
1605 [(set_attr "type" "mul")
1606 (set_attr "predicable" "yes")
1607 (set_attr "arch" "t2,v6,nov6,nov6")
1608 (set_attr "length" "4")
1609 (set_attr "predicable_short_it" "yes,no,*,*")]
1610 )
1611
1612 ;; MLA and MLS instruction. Use operand 1 for the accumulator to prefer
1613 ;; reusing the same register.
1614
1615 (define_insn "*mla"
1616 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r,&r")
1617 (plus:SI
1618 (mult:SI (match_operand:SI 3 "s_register_operand" "r,r,r,r")
1619 (match_operand:SI 2 "s_register_operand" "%r,r,0,r"))
1620 (match_operand:SI 1 "s_register_operand" "r,0,r,r")))]
1621 "TARGET_32BIT"
1622 "mla%?\\t%0, %3, %2, %1"
1623 [(set_attr "type" "mla")
1624 (set_attr "predicable" "yes")
1625 (set_attr "arch" "v6,nov6,nov6,nov6")]
1626 )
1627
1628 (define_insn "*mls"
1629 [(set (match_operand:SI 0 "s_register_operand" "=r")
1630 (minus:SI
1631 (match_operand:SI 1 "s_register_operand" "r")
1632 (mult:SI (match_operand:SI 3 "s_register_operand" "r")
1633 (match_operand:SI 2 "s_register_operand" "r"))))]
1634 "TARGET_32BIT && arm_arch_thumb2"
1635 "mls%?\\t%0, %3, %2, %1"
1636 [(set_attr "type" "mla")
1637 (set_attr "predicable" "yes")]
1638 )
1639
1640 (define_insn "*mulsi3_compare0"
1641 [(set (reg:CC_NOOV CC_REGNUM)
1642 (compare:CC_NOOV (mult:SI
1643 (match_operand:SI 2 "s_register_operand" "r,r")
1644 (match_operand:SI 1 "s_register_operand" "%0,r"))
1645 (const_int 0)))
1646 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1647 (mult:SI (match_dup 2) (match_dup 1)))]
1648 "TARGET_ARM && !arm_arch6"
1649 "muls%?\\t%0, %2, %1"
1650 [(set_attr "conds" "set")
1651 (set_attr "type" "muls")]
1652 )
1653
1654 (define_insn "*mulsi3_compare0_v6"
1655 [(set (reg:CC_NOOV CC_REGNUM)
1656 (compare:CC_NOOV (mult:SI
1657 (match_operand:SI 2 "s_register_operand" "r")
1658 (match_operand:SI 1 "s_register_operand" "r"))
1659 (const_int 0)))
1660 (set (match_operand:SI 0 "s_register_operand" "=r")
1661 (mult:SI (match_dup 2) (match_dup 1)))]
1662 "TARGET_ARM && arm_arch6 && optimize_size"
1663 "muls%?\\t%0, %2, %1"
1664 [(set_attr "conds" "set")
1665 (set_attr "type" "muls")]
1666 )
1667
1668 (define_insn "*mulsi_compare0_scratch"
1669 [(set (reg:CC_NOOV CC_REGNUM)
1670 (compare:CC_NOOV (mult:SI
1671 (match_operand:SI 2 "s_register_operand" "r,r")
1672 (match_operand:SI 1 "s_register_operand" "%0,r"))
1673 (const_int 0)))
1674 (clobber (match_scratch:SI 0 "=&r,&r"))]
1675 "TARGET_ARM && !arm_arch6"
1676 "muls%?\\t%0, %2, %1"
1677 [(set_attr "conds" "set")
1678 (set_attr "type" "muls")]
1679 )
1680
1681 (define_insn "*mulsi_compare0_scratch_v6"
1682 [(set (reg:CC_NOOV CC_REGNUM)
1683 (compare:CC_NOOV (mult:SI
1684 (match_operand:SI 2 "s_register_operand" "r")
1685 (match_operand:SI 1 "s_register_operand" "r"))
1686 (const_int 0)))
1687 (clobber (match_scratch:SI 0 "=r"))]
1688 "TARGET_ARM && arm_arch6 && optimize_size"
1689 "muls%?\\t%0, %2, %1"
1690 [(set_attr "conds" "set")
1691 (set_attr "type" "muls")]
1692 )
1693
1694 (define_insn "*mulsi3addsi_compare0"
1695 [(set (reg:CC_NOOV CC_REGNUM)
1696 (compare:CC_NOOV
1697 (plus:SI (mult:SI
1698 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1699 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1700 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1701 (const_int 0)))
1702 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1703 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1704 (match_dup 3)))]
1705 "TARGET_ARM && arm_arch6"
1706 "mlas%?\\t%0, %2, %1, %3"
1707 [(set_attr "conds" "set")
1708 (set_attr "type" "mlas")]
1709 )
1710
1711 (define_insn "*mulsi3addsi_compare0_v6"
1712 [(set (reg:CC_NOOV CC_REGNUM)
1713 (compare:CC_NOOV
1714 (plus:SI (mult:SI
1715 (match_operand:SI 2 "s_register_operand" "r")
1716 (match_operand:SI 1 "s_register_operand" "r"))
1717 (match_operand:SI 3 "s_register_operand" "r"))
1718 (const_int 0)))
1719 (set (match_operand:SI 0 "s_register_operand" "=r")
1720 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1721 (match_dup 3)))]
1722 "TARGET_ARM && arm_arch6 && optimize_size"
1723 "mlas%?\\t%0, %2, %1, %3"
1724 [(set_attr "conds" "set")
1725 (set_attr "type" "mlas")]
1726 )
1727
1728 (define_insn "*mulsi3addsi_compare0_scratch"
1729 [(set (reg:CC_NOOV CC_REGNUM)
1730 (compare:CC_NOOV
1731 (plus:SI (mult:SI
1732 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1733 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1734 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1735 (const_int 0)))
1736 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1737 "TARGET_ARM && !arm_arch6"
1738 "mlas%?\\t%0, %2, %1, %3"
1739 [(set_attr "conds" "set")
1740 (set_attr "type" "mlas")]
1741 )
1742
1743 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1744 [(set (reg:CC_NOOV CC_REGNUM)
1745 (compare:CC_NOOV
1746 (plus:SI (mult:SI
1747 (match_operand:SI 2 "s_register_operand" "r")
1748 (match_operand:SI 1 "s_register_operand" "r"))
1749 (match_operand:SI 3 "s_register_operand" "r"))
1750 (const_int 0)))
1751 (clobber (match_scratch:SI 0 "=r"))]
1752 "TARGET_ARM && arm_arch6 && optimize_size"
1753 "mlas%?\\t%0, %2, %1, %3"
1754 [(set_attr "conds" "set")
1755 (set_attr "type" "mlas")]
1756 )
1757
1758 ;; 32x32->64 widening multiply.
1759 ;; The only difference between the v3-5 and v6+ versions is the requirement
1760 ;; that the output does not overlap with either input.
1761
1762 (define_expand "<Us>mulsidi3"
1763 [(set (match_operand:DI 0 "s_register_operand")
1764 (mult:DI
1765 (SE:DI (match_operand:SI 1 "s_register_operand"))
1766 (SE:DI (match_operand:SI 2 "s_register_operand"))))]
1767 "TARGET_32BIT"
1768 {
1769 emit_insn (gen_<US>mull (gen_lowpart (SImode, operands[0]),
1770 gen_highpart (SImode, operands[0]),
1771 operands[1], operands[2]));
1772 DONE;
1773 }
1774 )
1775
1776 (define_insn "<US>mull"
1777 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1778 (mult:SI
1779 (match_operand:SI 2 "s_register_operand" "%r,r")
1780 (match_operand:SI 3 "s_register_operand" "r,r")))
1781 (set (match_operand:SI 1 "s_register_operand" "=r,&r")
1782 (truncate:SI
1783 (lshiftrt:DI
1784 (mult:DI (SE:DI (match_dup 2)) (SE:DI (match_dup 3)))
1785 (const_int 32))))]
1786 "TARGET_32BIT"
1787 "<US>mull%?\\t%0, %1, %2, %3"
1788 [(set_attr "type" "umull")
1789 (set_attr "predicable" "yes")
1790 (set_attr "arch" "v6,nov6")]
1791 )
1792
1793 (define_expand "<Us>maddsidi4"
1794 [(set (match_operand:DI 0 "s_register_operand")
1795 (plus:DI
1796 (mult:DI
1797 (SE:DI (match_operand:SI 1 "s_register_operand"))
1798 (SE:DI (match_operand:SI 2 "s_register_operand")))
1799 (match_operand:DI 3 "s_register_operand")))]
1800 "TARGET_32BIT"
1801 {
1802 emit_insn (gen_<US>mlal (gen_lowpart (SImode, operands[0]),
1803 gen_lowpart (SImode, operands[3]),
1804 gen_highpart (SImode, operands[0]),
1805 gen_highpart (SImode, operands[3]),
1806 operands[1], operands[2]));
1807 DONE;
1808 }
1809 )
1810
1811 (define_insn "<US>mlal"
1812 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1813 (plus:SI
1814 (mult:SI
1815 (SE:DI (match_operand:SI 4 "s_register_operand" "%r,r"))
1816 (SE:DI (match_operand:SI 5 "s_register_operand" "r,r")))
1817 (match_operand:SI 1 "s_register_operand" "0,0")))
1818 (set (match_operand:SI 2 "s_register_operand" "=r,&r")
1819 (plus:SI
1820 (truncate:SI
1821 (lshiftrt:DI
1822 (plus:DI
1823 (mult:DI (SE:DI (match_dup 4)) (SE:DI (match_dup 5)))
1824 (zero_extend:DI (match_dup 1)))
1825 (const_int 32)))
1826 (match_operand:SI 3 "s_register_operand" "2,2")))]
1827 "TARGET_32BIT"
1828 "<US>mlal%?\\t%0, %2, %4, %5"
1829 [(set_attr "type" "umlal")
1830 (set_attr "predicable" "yes")
1831 (set_attr "arch" "v6,nov6")]
1832 )
1833
1834 (define_expand "<US>mulsi3_highpart"
1835 [(parallel
1836 [(set (match_operand:SI 0 "s_register_operand")
1837 (truncate:SI
1838 (lshiftrt:DI
1839 (mult:DI
1840 (SE:DI (match_operand:SI 1 "s_register_operand"))
1841 (SE:DI (match_operand:SI 2 "s_register_operand")))
1842 (const_int 32))))
1843 (clobber (match_scratch:SI 3 ""))])]
1844 "TARGET_32BIT"
1845 ""
1846 )
1847
1848 (define_insn "*<US>mull_high"
1849 [(set (match_operand:SI 0 "s_register_operand" "=r,&r,&r")
1850 (truncate:SI
1851 (lshiftrt:DI
1852 (mult:DI
1853 (SE:DI (match_operand:SI 1 "s_register_operand" "%r,0,r"))
1854 (SE:DI (match_operand:SI 2 "s_register_operand" "r,r,r")))
1855 (const_int 32))))
1856 (clobber (match_scratch:SI 3 "=r,&r,&r"))]
1857 "TARGET_32BIT"
1858 "<US>mull%?\\t%3, %0, %2, %1"
1859 [(set_attr "type" "umull")
1860 (set_attr "predicable" "yes")
1861 (set_attr "arch" "v6,nov6,nov6")]
1862 )
1863
1864 (define_insn "mulhisi3"
1865 [(set (match_operand:SI 0 "s_register_operand" "=r")
1866 (mult:SI (sign_extend:SI
1867 (match_operand:HI 1 "s_register_operand" "%r"))
1868 (sign_extend:SI
1869 (match_operand:HI 2 "s_register_operand" "r"))))]
1870 "TARGET_DSP_MULTIPLY"
1871 "smulbb%?\\t%0, %1, %2"
1872 [(set_attr "type" "smulxy")
1873 (set_attr "predicable" "yes")]
1874 )
1875
1876 (define_insn "*mulhisi3tb"
1877 [(set (match_operand:SI 0 "s_register_operand" "=r")
1878 (mult:SI (ashiftrt:SI
1879 (match_operand:SI 1 "s_register_operand" "r")
1880 (const_int 16))
1881 (sign_extend:SI
1882 (match_operand:HI 2 "s_register_operand" "r"))))]
1883 "TARGET_DSP_MULTIPLY"
1884 "smultb%?\\t%0, %1, %2"
1885 [(set_attr "type" "smulxy")
1886 (set_attr "predicable" "yes")]
1887 )
1888
1889 (define_insn "*mulhisi3bt"
1890 [(set (match_operand:SI 0 "s_register_operand" "=r")
1891 (mult:SI (sign_extend:SI
1892 (match_operand:HI 1 "s_register_operand" "r"))
1893 (ashiftrt:SI
1894 (match_operand:SI 2 "s_register_operand" "r")
1895 (const_int 16))))]
1896 "TARGET_DSP_MULTIPLY"
1897 "smulbt%?\\t%0, %1, %2"
1898 [(set_attr "type" "smulxy")
1899 (set_attr "predicable" "yes")]
1900 )
1901
1902 (define_insn "*mulhisi3tt"
1903 [(set (match_operand:SI 0 "s_register_operand" "=r")
1904 (mult:SI (ashiftrt:SI
1905 (match_operand:SI 1 "s_register_operand" "r")
1906 (const_int 16))
1907 (ashiftrt:SI
1908 (match_operand:SI 2 "s_register_operand" "r")
1909 (const_int 16))))]
1910 "TARGET_DSP_MULTIPLY"
1911 "smultt%?\\t%0, %1, %2"
1912 [(set_attr "type" "smulxy")
1913 (set_attr "predicable" "yes")]
1914 )
1915
1916 (define_insn "maddhisi4"
1917 [(set (match_operand:SI 0 "s_register_operand" "=r")
1918 (plus:SI (mult:SI (sign_extend:SI
1919 (match_operand:HI 1 "s_register_operand" "r"))
1920 (sign_extend:SI
1921 (match_operand:HI 2 "s_register_operand" "r")))
1922 (match_operand:SI 3 "s_register_operand" "r")))]
1923 "TARGET_DSP_MULTIPLY"
1924 "smlabb%?\\t%0, %1, %2, %3"
1925 [(set_attr "type" "smlaxy")
1926 (set_attr "predicable" "yes")]
1927 )
1928
1929 ;; Note: there is no maddhisi4ibt because this one is canonical form
1930 (define_insn "*maddhisi4tb"
1931 [(set (match_operand:SI 0 "s_register_operand" "=r")
1932 (plus:SI (mult:SI (ashiftrt:SI
1933 (match_operand:SI 1 "s_register_operand" "r")
1934 (const_int 16))
1935 (sign_extend:SI
1936 (match_operand:HI 2 "s_register_operand" "r")))
1937 (match_operand:SI 3 "s_register_operand" "r")))]
1938 "TARGET_DSP_MULTIPLY"
1939 "smlatb%?\\t%0, %1, %2, %3"
1940 [(set_attr "type" "smlaxy")
1941 (set_attr "predicable" "yes")]
1942 )
1943
1944 (define_insn "*maddhisi4tt"
1945 [(set (match_operand:SI 0 "s_register_operand" "=r")
1946 (plus:SI (mult:SI (ashiftrt:SI
1947 (match_operand:SI 1 "s_register_operand" "r")
1948 (const_int 16))
1949 (ashiftrt:SI
1950 (match_operand:SI 2 "s_register_operand" "r")
1951 (const_int 16)))
1952 (match_operand:SI 3 "s_register_operand" "r")))]
1953 "TARGET_DSP_MULTIPLY"
1954 "smlatt%?\\t%0, %1, %2, %3"
1955 [(set_attr "type" "smlaxy")
1956 (set_attr "predicable" "yes")]
1957 )
1958
1959 (define_insn "maddhidi4"
1960 [(set (match_operand:DI 0 "s_register_operand" "=r")
1961 (plus:DI
1962 (mult:DI (sign_extend:DI
1963 (match_operand:HI 1 "s_register_operand" "r"))
1964 (sign_extend:DI
1965 (match_operand:HI 2 "s_register_operand" "r")))
1966 (match_operand:DI 3 "s_register_operand" "0")))]
1967 "TARGET_DSP_MULTIPLY"
1968 "smlalbb%?\\t%Q0, %R0, %1, %2"
1969 [(set_attr "type" "smlalxy")
1970 (set_attr "predicable" "yes")])
1971
1972 ;; Note: there is no maddhidi4ibt because this one is canonical form
1973 (define_insn "*maddhidi4tb"
1974 [(set (match_operand:DI 0 "s_register_operand" "=r")
1975 (plus:DI
1976 (mult:DI (sign_extend:DI
1977 (ashiftrt:SI
1978 (match_operand:SI 1 "s_register_operand" "r")
1979 (const_int 16)))
1980 (sign_extend:DI
1981 (match_operand:HI 2 "s_register_operand" "r")))
1982 (match_operand:DI 3 "s_register_operand" "0")))]
1983 "TARGET_DSP_MULTIPLY"
1984 "smlaltb%?\\t%Q0, %R0, %1, %2"
1985 [(set_attr "type" "smlalxy")
1986 (set_attr "predicable" "yes")])
1987
1988 (define_insn "*maddhidi4tt"
1989 [(set (match_operand:DI 0 "s_register_operand" "=r")
1990 (plus:DI
1991 (mult:DI (sign_extend:DI
1992 (ashiftrt:SI
1993 (match_operand:SI 1 "s_register_operand" "r")
1994 (const_int 16)))
1995 (sign_extend:DI
1996 (ashiftrt:SI
1997 (match_operand:SI 2 "s_register_operand" "r")
1998 (const_int 16))))
1999 (match_operand:DI 3 "s_register_operand" "0")))]
2000 "TARGET_DSP_MULTIPLY"
2001 "smlaltt%?\\t%Q0, %R0, %1, %2"
2002 [(set_attr "type" "smlalxy")
2003 (set_attr "predicable" "yes")])
2004
2005 (define_expand "mulsf3"
2006 [(set (match_operand:SF 0 "s_register_operand")
2007 (mult:SF (match_operand:SF 1 "s_register_operand")
2008 (match_operand:SF 2 "s_register_operand")))]
2009 "TARGET_32BIT && TARGET_HARD_FLOAT"
2010 "
2011 ")
2012
2013 (define_expand "muldf3"
2014 [(set (match_operand:DF 0 "s_register_operand")
2015 (mult:DF (match_operand:DF 1 "s_register_operand")
2016 (match_operand:DF 2 "s_register_operand")))]
2017 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
2018 "
2019 ")
2020 \f
2021 ;; Division insns
2022
2023 (define_expand "divsf3"
2024 [(set (match_operand:SF 0 "s_register_operand")
2025 (div:SF (match_operand:SF 1 "s_register_operand")
2026 (match_operand:SF 2 "s_register_operand")))]
2027 "TARGET_32BIT && TARGET_HARD_FLOAT"
2028 "")
2029
2030 (define_expand "divdf3"
2031 [(set (match_operand:DF 0 "s_register_operand")
2032 (div:DF (match_operand:DF 1 "s_register_operand")
2033 (match_operand:DF 2 "s_register_operand")))]
2034 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
2035 "")
2036 \f
2037
2038 ; Expand logical operations. The mid-end expander does not split off memory
2039 ; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
2040 ; So an explicit expander is needed to generate better code.
2041
2042 (define_expand "<LOGICAL:optab>di3"
2043 [(set (match_operand:DI 0 "s_register_operand")
2044 (LOGICAL:DI (match_operand:DI 1 "s_register_operand")
2045 (match_operand:DI 2 "arm_<optab>di_operand")))]
2046 "TARGET_32BIT"
2047 {
2048 rtx low = simplify_gen_binary (<CODE>, SImode,
2049 gen_lowpart (SImode, operands[1]),
2050 gen_lowpart (SImode, operands[2]));
2051 rtx high = simplify_gen_binary (<CODE>, SImode,
2052 gen_highpart (SImode, operands[1]),
2053 gen_highpart_mode (SImode, DImode,
2054 operands[2]));
2055
2056 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2057 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2058 DONE;
2059 }
2060 )
2061
2062 (define_expand "one_cmpldi2"
2063 [(set (match_operand:DI 0 "s_register_operand")
2064 (not:DI (match_operand:DI 1 "s_register_operand")))]
2065 "TARGET_32BIT"
2066 {
2067 rtx low = simplify_gen_unary (NOT, SImode,
2068 gen_lowpart (SImode, operands[1]),
2069 SImode);
2070 rtx high = simplify_gen_unary (NOT, SImode,
2071 gen_highpart_mode (SImode, DImode,
2072 operands[1]),
2073 SImode);
2074
2075 emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
2076 emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
2077 DONE;
2078 }
2079 )
2080
2081 ;; Split DImode and, ior, xor operations. Simply perform the logical
2082 ;; operation on the upper and lower halves of the registers.
2083 ;; This is needed for atomic operations in arm_split_atomic_op.
2084 ;; Avoid splitting IWMMXT instructions.
2085 (define_split
2086 [(set (match_operand:DI 0 "s_register_operand" "")
2087 (match_operator:DI 6 "logical_binary_operator"
2088 [(match_operand:DI 1 "s_register_operand" "")
2089 (match_operand:DI 2 "s_register_operand" "")]))]
2090 "TARGET_32BIT && reload_completed
2091 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2092 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2093 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2094 "
2095 {
2096 operands[3] = gen_highpart (SImode, operands[0]);
2097 operands[0] = gen_lowpart (SImode, operands[0]);
2098 operands[4] = gen_highpart (SImode, operands[1]);
2099 operands[1] = gen_lowpart (SImode, operands[1]);
2100 operands[5] = gen_highpart (SImode, operands[2]);
2101 operands[2] = gen_lowpart (SImode, operands[2]);
2102 }"
2103 )
2104
2105 ;; Split DImode not (needed for atomic operations in arm_split_atomic_op).
2106 ;; Unconditionally split since there is no SIMD DImode NOT pattern.
2107 (define_split
2108 [(set (match_operand:DI 0 "s_register_operand")
2109 (not:DI (match_operand:DI 1 "s_register_operand")))]
2110 "TARGET_32BIT"
2111 [(set (match_dup 0) (not:SI (match_dup 1)))
2112 (set (match_dup 2) (not:SI (match_dup 3)))]
2113 "
2114 {
2115 operands[2] = gen_highpart (SImode, operands[0]);
2116 operands[0] = gen_lowpart (SImode, operands[0]);
2117 operands[3] = gen_highpart (SImode, operands[1]);
2118 operands[1] = gen_lowpart (SImode, operands[1]);
2119 }"
2120 )
2121
2122 (define_expand "andsi3"
2123 [(set (match_operand:SI 0 "s_register_operand")
2124 (and:SI (match_operand:SI 1 "s_register_operand")
2125 (match_operand:SI 2 "reg_or_int_operand")))]
2126 "TARGET_EITHER"
2127 "
2128 if (TARGET_32BIT)
2129 {
2130 if (CONST_INT_P (operands[2]))
2131 {
2132 if (INTVAL (operands[2]) == 255 && arm_arch6)
2133 {
2134 operands[1] = convert_to_mode (QImode, operands[1], 1);
2135 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2136 operands[1]));
2137 DONE;
2138 }
2139 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2140 operands[2] = force_reg (SImode, operands[2]);
2141 else
2142 {
2143 arm_split_constant (AND, SImode, NULL_RTX,
2144 INTVAL (operands[2]), operands[0],
2145 operands[1],
2146 optimize && can_create_pseudo_p ());
2147
2148 DONE;
2149 }
2150 }
2151 }
2152 else /* TARGET_THUMB1 */
2153 {
2154 if (!CONST_INT_P (operands[2]))
2155 {
2156 rtx tmp = force_reg (SImode, operands[2]);
2157 if (rtx_equal_p (operands[0], operands[1]))
2158 operands[2] = tmp;
2159 else
2160 {
2161 operands[2] = operands[1];
2162 operands[1] = tmp;
2163 }
2164 }
2165 else
2166 {
2167 int i;
2168
2169 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2170 {
2171 operands[2] = force_reg (SImode,
2172 GEN_INT (~INTVAL (operands[2])));
2173
2174 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2175
2176 DONE;
2177 }
2178
2179 for (i = 9; i <= 31; i++)
2180 {
2181 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
2182 {
2183 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2184 const0_rtx));
2185 DONE;
2186 }
2187 else if ((HOST_WIDE_INT_1 << i) - 1
2188 == ~INTVAL (operands[2]))
2189 {
2190 rtx shift = GEN_INT (i);
2191 rtx reg = gen_reg_rtx (SImode);
2192
2193 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2194 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2195
2196 DONE;
2197 }
2198 }
2199
2200 operands[2] = force_reg (SImode, operands[2]);
2201 }
2202 }
2203 "
2204 )
2205
2206 ; ??? Check split length for Thumb-2
2207 (define_insn_and_split "*arm_andsi3_insn"
2208 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2209 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2210 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
2211 "TARGET_32BIT"
2212 "@
2213 and%?\\t%0, %1, %2
2214 and%?\\t%0, %1, %2
2215 bic%?\\t%0, %1, #%B2
2216 and%?\\t%0, %1, %2
2217 #"
2218 "TARGET_32BIT
2219 && CONST_INT_P (operands[2])
2220 && !(const_ok_for_arm (INTVAL (operands[2]))
2221 || const_ok_for_arm (~INTVAL (operands[2])))"
2222 [(clobber (const_int 0))]
2223 "
2224 arm_split_constant (AND, SImode, curr_insn,
2225 INTVAL (operands[2]), operands[0], operands[1], 0);
2226 DONE;
2227 "
2228 [(set_attr "length" "4,4,4,4,16")
2229 (set_attr "predicable" "yes")
2230 (set_attr "predicable_short_it" "no,yes,no,no,no")
2231 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
2232 )
2233
2234 (define_insn "*andsi3_compare0"
2235 [(set (reg:CC_NOOV CC_REGNUM)
2236 (compare:CC_NOOV
2237 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2238 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
2239 (const_int 0)))
2240 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2241 (and:SI (match_dup 1) (match_dup 2)))]
2242 "TARGET_32BIT"
2243 "@
2244 ands%?\\t%0, %1, %2
2245 bics%?\\t%0, %1, #%B2
2246 ands%?\\t%0, %1, %2"
2247 [(set_attr "conds" "set")
2248 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2249 )
2250
2251 (define_insn "*andsi3_compare0_scratch"
2252 [(set (reg:CC_NOOV CC_REGNUM)
2253 (compare:CC_NOOV
2254 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2255 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
2256 (const_int 0)))
2257 (clobber (match_scratch:SI 2 "=X,r,X"))]
2258 "TARGET_32BIT"
2259 "@
2260 tst%?\\t%0, %1
2261 bics%?\\t%2, %0, #%B1
2262 tst%?\\t%0, %1"
2263 [(set_attr "conds" "set")
2264 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2265 )
2266
2267 (define_insn "*zeroextractsi_compare0_scratch"
2268 [(set (reg:CC_NOOV CC_REGNUM)
2269 (compare:CC_NOOV (zero_extract:SI
2270 (match_operand:SI 0 "s_register_operand" "r")
2271 (match_operand 1 "const_int_operand" "n")
2272 (match_operand 2 "const_int_operand" "n"))
2273 (const_int 0)))]
2274 "TARGET_32BIT
2275 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2276 && INTVAL (operands[1]) > 0
2277 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2278 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2279 "*
2280 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2281 << INTVAL (operands[2]));
2282 output_asm_insn (\"tst%?\\t%0, %1\", operands);
2283 return \"\";
2284 "
2285 [(set_attr "conds" "set")
2286 (set_attr "predicable" "yes")
2287 (set_attr "type" "logics_imm")]
2288 )
2289
2290 (define_insn_and_split "*ne_zeroextractsi"
2291 [(set (match_operand:SI 0 "s_register_operand" "=r")
2292 (ne:SI (zero_extract:SI
2293 (match_operand:SI 1 "s_register_operand" "r")
2294 (match_operand:SI 2 "const_int_operand" "n")
2295 (match_operand:SI 3 "const_int_operand" "n"))
2296 (const_int 0)))
2297 (clobber (reg:CC CC_REGNUM))]
2298 "TARGET_32BIT
2299 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2300 && INTVAL (operands[2]) > 0
2301 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2302 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2303 "#"
2304 "TARGET_32BIT
2305 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2306 && INTVAL (operands[2]) > 0
2307 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2308 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2309 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2310 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2311 (const_int 0)))
2312 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2313 (set (match_dup 0)
2314 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2315 (match_dup 0) (const_int 1)))]
2316 "
2317 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2318 << INTVAL (operands[3]));
2319 "
2320 [(set_attr "conds" "clob")
2321 (set (attr "length")
2322 (if_then_else (eq_attr "is_thumb" "yes")
2323 (const_int 12)
2324 (const_int 8)))
2325 (set_attr "type" "multiple")]
2326 )
2327
2328 (define_insn_and_split "*ne_zeroextractsi_shifted"
2329 [(set (match_operand:SI 0 "s_register_operand" "=r")
2330 (ne:SI (zero_extract:SI
2331 (match_operand:SI 1 "s_register_operand" "r")
2332 (match_operand:SI 2 "const_int_operand" "n")
2333 (const_int 0))
2334 (const_int 0)))
2335 (clobber (reg:CC CC_REGNUM))]
2336 "TARGET_ARM"
2337 "#"
2338 "TARGET_ARM"
2339 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2340 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2341 (const_int 0)))
2342 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2343 (set (match_dup 0)
2344 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2345 (match_dup 0) (const_int 1)))]
2346 "
2347 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2348 "
2349 [(set_attr "conds" "clob")
2350 (set_attr "length" "8")
2351 (set_attr "type" "multiple")]
2352 )
2353
2354 (define_insn_and_split "*ite_ne_zeroextractsi"
2355 [(set (match_operand:SI 0 "s_register_operand" "=r")
2356 (if_then_else:SI (ne (zero_extract:SI
2357 (match_operand:SI 1 "s_register_operand" "r")
2358 (match_operand:SI 2 "const_int_operand" "n")
2359 (match_operand:SI 3 "const_int_operand" "n"))
2360 (const_int 0))
2361 (match_operand:SI 4 "arm_not_operand" "rIK")
2362 (const_int 0)))
2363 (clobber (reg:CC CC_REGNUM))]
2364 "TARGET_ARM
2365 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2366 && INTVAL (operands[2]) > 0
2367 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2368 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2369 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2370 "#"
2371 "TARGET_ARM
2372 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2373 && INTVAL (operands[2]) > 0
2374 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2375 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2376 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2377 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2378 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2379 (const_int 0)))
2380 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2381 (set (match_dup 0)
2382 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2383 (match_dup 0) (match_dup 4)))]
2384 "
2385 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2386 << INTVAL (operands[3]));
2387 "
2388 [(set_attr "conds" "clob")
2389 (set_attr "length" "8")
2390 (set_attr "type" "multiple")]
2391 )
2392
2393 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2394 [(set (match_operand:SI 0 "s_register_operand" "=r")
2395 (if_then_else:SI (ne (zero_extract:SI
2396 (match_operand:SI 1 "s_register_operand" "r")
2397 (match_operand:SI 2 "const_int_operand" "n")
2398 (const_int 0))
2399 (const_int 0))
2400 (match_operand:SI 3 "arm_not_operand" "rIK")
2401 (const_int 0)))
2402 (clobber (reg:CC CC_REGNUM))]
2403 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2404 "#"
2405 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2406 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2407 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2408 (const_int 0)))
2409 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2410 (set (match_dup 0)
2411 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2412 (match_dup 0) (match_dup 3)))]
2413 "
2414 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2415 "
2416 [(set_attr "conds" "clob")
2417 (set_attr "length" "8")
2418 (set_attr "type" "multiple")]
2419 )
2420
2421 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2422 (define_split
2423 [(set (match_operand:SI 0 "s_register_operand" "")
2424 (match_operator:SI 1 "shiftable_operator"
2425 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2426 (match_operand:SI 3 "const_int_operand" "")
2427 (match_operand:SI 4 "const_int_operand" ""))
2428 (match_operand:SI 5 "s_register_operand" "")]))
2429 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2430 "TARGET_ARM"
2431 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2432 (set (match_dup 0)
2433 (match_op_dup 1
2434 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2435 (match_dup 5)]))]
2436 "{
2437 HOST_WIDE_INT temp = INTVAL (operands[3]);
2438
2439 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2440 operands[4] = GEN_INT (32 - temp);
2441 }"
2442 )
2443
2444 (define_split
2445 [(set (match_operand:SI 0 "s_register_operand" "")
2446 (match_operator:SI 1 "shiftable_operator"
2447 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2448 (match_operand:SI 3 "const_int_operand" "")
2449 (match_operand:SI 4 "const_int_operand" ""))
2450 (match_operand:SI 5 "s_register_operand" "")]))
2451 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2452 "TARGET_ARM"
2453 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2454 (set (match_dup 0)
2455 (match_op_dup 1
2456 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2457 (match_dup 5)]))]
2458 "{
2459 HOST_WIDE_INT temp = INTVAL (operands[3]);
2460
2461 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2462 operands[4] = GEN_INT (32 - temp);
2463 }"
2464 )
2465
2466 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
2467 ;;; represented by the bitfield, then this will produce incorrect results.
2468 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
2469 ;;; which have a real bit-field insert instruction, the truncation happens
2470 ;;; in the bit-field insert instruction itself. Since arm does not have a
2471 ;;; bit-field insert instruction, we would have to emit code here to truncate
2472 ;;; the value before we insert. This loses some of the advantage of having
2473 ;;; this insv pattern, so this pattern needs to be reevalutated.
2474
2475 (define_expand "insv"
2476 [(set (zero_extract (match_operand 0 "nonimmediate_operand")
2477 (match_operand 1 "general_operand")
2478 (match_operand 2 "general_operand"))
2479 (match_operand 3 "reg_or_int_operand"))]
2480 "TARGET_ARM || arm_arch_thumb2"
2481 "
2482 {
2483 int start_bit = INTVAL (operands[2]);
2484 int width = INTVAL (operands[1]);
2485 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
2486 rtx target, subtarget;
2487
2488 if (arm_arch_thumb2)
2489 {
2490 if (unaligned_access && MEM_P (operands[0])
2491 && s_register_operand (operands[3], GET_MODE (operands[3]))
2492 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
2493 {
2494 rtx base_addr;
2495
2496 if (BYTES_BIG_ENDIAN)
2497 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2498 - start_bit;
2499
2500 if (width == 32)
2501 {
2502 base_addr = adjust_address (operands[0], SImode,
2503 start_bit / BITS_PER_UNIT);
2504 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
2505 }
2506 else
2507 {
2508 rtx tmp = gen_reg_rtx (HImode);
2509
2510 base_addr = adjust_address (operands[0], HImode,
2511 start_bit / BITS_PER_UNIT);
2512 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2513 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2514 }
2515 DONE;
2516 }
2517 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
2518 {
2519 bool use_bfi = TRUE;
2520
2521 if (CONST_INT_P (operands[3]))
2522 {
2523 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2524
2525 if (val == 0)
2526 {
2527 emit_insn (gen_insv_zero (operands[0], operands[1],
2528 operands[2]));
2529 DONE;
2530 }
2531
2532 /* See if the set can be done with a single orr instruction. */
2533 if (val == mask && const_ok_for_arm (val << start_bit))
2534 use_bfi = FALSE;
2535 }
2536
2537 if (use_bfi)
2538 {
2539 if (!REG_P (operands[3]))
2540 operands[3] = force_reg (SImode, operands[3]);
2541
2542 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2543 operands[3]));
2544 DONE;
2545 }
2546 }
2547 else
2548 FAIL;
2549 }
2550
2551 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2552 FAIL;
2553
2554 target = copy_rtx (operands[0]);
2555 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2556 subreg as the final target. */
2557 if (GET_CODE (target) == SUBREG)
2558 {
2559 subtarget = gen_reg_rtx (SImode);
2560 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2561 < GET_MODE_SIZE (SImode))
2562 target = SUBREG_REG (target);
2563 }
2564 else
2565 subtarget = target;
2566
2567 if (CONST_INT_P (operands[3]))
2568 {
2569 /* Since we are inserting a known constant, we may be able to
2570 reduce the number of bits that we have to clear so that
2571 the mask becomes simple. */
2572 /* ??? This code does not check to see if the new mask is actually
2573 simpler. It may not be. */
2574 rtx op1 = gen_reg_rtx (SImode);
2575 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2576 start of this pattern. */
2577 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2578 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2579
2580 emit_insn (gen_andsi3 (op1, operands[0],
2581 gen_int_mode (~mask2, SImode)));
2582 emit_insn (gen_iorsi3 (subtarget, op1,
2583 gen_int_mode (op3_value << start_bit, SImode)));
2584 }
2585 else if (start_bit == 0
2586 && !(const_ok_for_arm (mask)
2587 || const_ok_for_arm (~mask)))
2588 {
2589 /* A Trick, since we are setting the bottom bits in the word,
2590 we can shift operand[3] up, operand[0] down, OR them together
2591 and rotate the result back again. This takes 3 insns, and
2592 the third might be mergeable into another op. */
2593 /* The shift up copes with the possibility that operand[3] is
2594 wider than the bitfield. */
2595 rtx op0 = gen_reg_rtx (SImode);
2596 rtx op1 = gen_reg_rtx (SImode);
2597
2598 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2599 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2600 emit_insn (gen_iorsi3 (op1, op1, op0));
2601 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2602 }
2603 else if ((width + start_bit == 32)
2604 && !(const_ok_for_arm (mask)
2605 || const_ok_for_arm (~mask)))
2606 {
2607 /* Similar trick, but slightly less efficient. */
2608
2609 rtx op0 = gen_reg_rtx (SImode);
2610 rtx op1 = gen_reg_rtx (SImode);
2611
2612 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2613 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2614 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2615 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2616 }
2617 else
2618 {
2619 rtx op0 = gen_int_mode (mask, SImode);
2620 rtx op1 = gen_reg_rtx (SImode);
2621 rtx op2 = gen_reg_rtx (SImode);
2622
2623 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2624 {
2625 rtx tmp = gen_reg_rtx (SImode);
2626
2627 emit_insn (gen_movsi (tmp, op0));
2628 op0 = tmp;
2629 }
2630
2631 /* Mask out any bits in operand[3] that are not needed. */
2632 emit_insn (gen_andsi3 (op1, operands[3], op0));
2633
2634 if (CONST_INT_P (op0)
2635 && (const_ok_for_arm (mask << start_bit)
2636 || const_ok_for_arm (~(mask << start_bit))))
2637 {
2638 op0 = gen_int_mode (~(mask << start_bit), SImode);
2639 emit_insn (gen_andsi3 (op2, operands[0], op0));
2640 }
2641 else
2642 {
2643 if (CONST_INT_P (op0))
2644 {
2645 rtx tmp = gen_reg_rtx (SImode);
2646
2647 emit_insn (gen_movsi (tmp, op0));
2648 op0 = tmp;
2649 }
2650
2651 if (start_bit != 0)
2652 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2653
2654 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2655 }
2656
2657 if (start_bit != 0)
2658 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2659
2660 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2661 }
2662
2663 if (subtarget != target)
2664 {
2665 /* If TARGET is still a SUBREG, then it must be wider than a word,
2666 so we must be careful only to set the subword we were asked to. */
2667 if (GET_CODE (target) == SUBREG)
2668 emit_move_insn (target, subtarget);
2669 else
2670 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2671 }
2672
2673 DONE;
2674 }"
2675 )
2676
2677 (define_insn "insv_zero"
2678 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2679 (match_operand:SI 1 "const_int_M_operand" "M")
2680 (match_operand:SI 2 "const_int_M_operand" "M"))
2681 (const_int 0))]
2682 "arm_arch_thumb2"
2683 "bfc%?\t%0, %2, %1"
2684 [(set_attr "length" "4")
2685 (set_attr "predicable" "yes")
2686 (set_attr "type" "bfm")]
2687 )
2688
2689 (define_insn "insv_t2"
2690 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2691 (match_operand:SI 1 "const_int_M_operand" "M")
2692 (match_operand:SI 2 "const_int_M_operand" "M"))
2693 (match_operand:SI 3 "s_register_operand" "r"))]
2694 "arm_arch_thumb2"
2695 "bfi%?\t%0, %3, %2, %1"
2696 [(set_attr "length" "4")
2697 (set_attr "predicable" "yes")
2698 (set_attr "type" "bfm")]
2699 )
2700
2701 (define_insn "andsi_notsi_si"
2702 [(set (match_operand:SI 0 "s_register_operand" "=r")
2703 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2704 (match_operand:SI 1 "s_register_operand" "r")))]
2705 "TARGET_32BIT"
2706 "bic%?\\t%0, %1, %2"
2707 [(set_attr "predicable" "yes")
2708 (set_attr "type" "logic_reg")]
2709 )
2710
2711 (define_insn "andsi_not_shiftsi_si"
2712 [(set (match_operand:SI 0 "s_register_operand" "=r")
2713 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2714 [(match_operand:SI 2 "s_register_operand" "r")
2715 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2716 (match_operand:SI 1 "s_register_operand" "r")))]
2717 "TARGET_ARM"
2718 "bic%?\\t%0, %1, %2%S4"
2719 [(set_attr "predicable" "yes")
2720 (set_attr "shift" "2")
2721 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2722 (const_string "logic_shift_imm")
2723 (const_string "logic_shift_reg")))]
2724 )
2725
2726 ;; Shifted bics pattern used to set up CC status register and not reusing
2727 ;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2728 ;; does not support shift by register.
2729 (define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2730 [(set (reg:CC_NOOV CC_REGNUM)
2731 (compare:CC_NOOV
2732 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2733 [(match_operand:SI 1 "s_register_operand" "r")
2734 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2735 (match_operand:SI 3 "s_register_operand" "r"))
2736 (const_int 0)))
2737 (clobber (match_scratch:SI 4 "=r"))]
2738 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
2739 "bics%?\\t%4, %3, %1%S0"
2740 [(set_attr "predicable" "yes")
2741 (set_attr "conds" "set")
2742 (set_attr "shift" "1")
2743 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2744 (const_string "logic_shift_imm")
2745 (const_string "logic_shift_reg")))]
2746 )
2747
2748 ;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2749 ;; getting reused later.
2750 (define_insn "andsi_not_shiftsi_si_scc"
2751 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2752 (compare:CC_NOOV
2753 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2754 [(match_operand:SI 1 "s_register_operand" "r")
2755 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2756 (match_operand:SI 3 "s_register_operand" "r"))
2757 (const_int 0)))
2758 (set (match_operand:SI 4 "s_register_operand" "=r")
2759 (and:SI (not:SI (match_op_dup 0
2760 [(match_dup 1)
2761 (match_dup 2)]))
2762 (match_dup 3)))])]
2763 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
2764 "bics%?\\t%4, %3, %1%S0"
2765 [(set_attr "predicable" "yes")
2766 (set_attr "conds" "set")
2767 (set_attr "shift" "1")
2768 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2769 (const_string "logic_shift_imm")
2770 (const_string "logic_shift_reg")))]
2771 )
2772
2773 (define_insn "*andsi_notsi_si_compare0"
2774 [(set (reg:CC_NOOV CC_REGNUM)
2775 (compare:CC_NOOV
2776 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2777 (match_operand:SI 1 "s_register_operand" "r"))
2778 (const_int 0)))
2779 (set (match_operand:SI 0 "s_register_operand" "=r")
2780 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2781 "TARGET_32BIT"
2782 "bics\\t%0, %1, %2"
2783 [(set_attr "conds" "set")
2784 (set_attr "type" "logics_shift_reg")]
2785 )
2786
2787 (define_insn "*andsi_notsi_si_compare0_scratch"
2788 [(set (reg:CC_NOOV CC_REGNUM)
2789 (compare:CC_NOOV
2790 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2791 (match_operand:SI 1 "s_register_operand" "r"))
2792 (const_int 0)))
2793 (clobber (match_scratch:SI 0 "=r"))]
2794 "TARGET_32BIT"
2795 "bics\\t%0, %1, %2"
2796 [(set_attr "conds" "set")
2797 (set_attr "type" "logics_shift_reg")]
2798 )
2799
2800 (define_expand "iorsi3"
2801 [(set (match_operand:SI 0 "s_register_operand")
2802 (ior:SI (match_operand:SI 1 "s_register_operand")
2803 (match_operand:SI 2 "reg_or_int_operand")))]
2804 "TARGET_EITHER"
2805 "
2806 if (CONST_INT_P (operands[2]))
2807 {
2808 if (TARGET_32BIT)
2809 {
2810 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2811 operands[2] = force_reg (SImode, operands[2]);
2812 else
2813 {
2814 arm_split_constant (IOR, SImode, NULL_RTX,
2815 INTVAL (operands[2]), operands[0],
2816 operands[1],
2817 optimize && can_create_pseudo_p ());
2818 DONE;
2819 }
2820 }
2821 else /* TARGET_THUMB1 */
2822 {
2823 rtx tmp = force_reg (SImode, operands[2]);
2824 if (rtx_equal_p (operands[0], operands[1]))
2825 operands[2] = tmp;
2826 else
2827 {
2828 operands[2] = operands[1];
2829 operands[1] = tmp;
2830 }
2831 }
2832 }
2833 "
2834 )
2835
2836 (define_insn_and_split "*iorsi3_insn"
2837 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2838 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2839 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
2840 "TARGET_32BIT"
2841 "@
2842 orr%?\\t%0, %1, %2
2843 orr%?\\t%0, %1, %2
2844 orn%?\\t%0, %1, #%B2
2845 orr%?\\t%0, %1, %2
2846 #"
2847 "TARGET_32BIT
2848 && CONST_INT_P (operands[2])
2849 && !(const_ok_for_arm (INTVAL (operands[2]))
2850 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
2851 [(clobber (const_int 0))]
2852 {
2853 arm_split_constant (IOR, SImode, curr_insn,
2854 INTVAL (operands[2]), operands[0], operands[1], 0);
2855 DONE;
2856 }
2857 [(set_attr "length" "4,4,4,4,16")
2858 (set_attr "arch" "32,t2,t2,32,32")
2859 (set_attr "predicable" "yes")
2860 (set_attr "predicable_short_it" "no,yes,no,no,no")
2861 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
2862 )
2863
2864 (define_peephole2
2865 [(match_scratch:SI 3 "r")
2866 (set (match_operand:SI 0 "arm_general_register_operand" "")
2867 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2868 (match_operand:SI 2 "const_int_operand" "")))]
2869 "TARGET_ARM
2870 && !const_ok_for_arm (INTVAL (operands[2]))
2871 && const_ok_for_arm (~INTVAL (operands[2]))"
2872 [(set (match_dup 3) (match_dup 2))
2873 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2874 ""
2875 )
2876
2877 (define_insn "*iorsi3_compare0"
2878 [(set (reg:CC_NOOV CC_REGNUM)
2879 (compare:CC_NOOV
2880 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2881 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2882 (const_int 0)))
2883 (set (match_operand:SI 0 "s_register_operand" "=r,l,r")
2884 (ior:SI (match_dup 1) (match_dup 2)))]
2885 "TARGET_32BIT"
2886 "orrs%?\\t%0, %1, %2"
2887 [(set_attr "conds" "set")
2888 (set_attr "arch" "*,t2,*")
2889 (set_attr "length" "4,2,4")
2890 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
2891 )
2892
2893 (define_insn "*iorsi3_compare0_scratch"
2894 [(set (reg:CC_NOOV CC_REGNUM)
2895 (compare:CC_NOOV
2896 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2897 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2898 (const_int 0)))
2899 (clobber (match_scratch:SI 0 "=r,l,r"))]
2900 "TARGET_32BIT"
2901 "orrs%?\\t%0, %1, %2"
2902 [(set_attr "conds" "set")
2903 (set_attr "arch" "*,t2,*")
2904 (set_attr "length" "4,2,4")
2905 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
2906 )
2907
2908 (define_expand "xorsi3"
2909 [(set (match_operand:SI 0 "s_register_operand")
2910 (xor:SI (match_operand:SI 1 "s_register_operand")
2911 (match_operand:SI 2 "reg_or_int_operand")))]
2912 "TARGET_EITHER"
2913 "if (CONST_INT_P (operands[2]))
2914 {
2915 if (TARGET_32BIT)
2916 {
2917 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
2918 operands[2] = force_reg (SImode, operands[2]);
2919 else
2920 {
2921 arm_split_constant (XOR, SImode, NULL_RTX,
2922 INTVAL (operands[2]), operands[0],
2923 operands[1],
2924 optimize && can_create_pseudo_p ());
2925 DONE;
2926 }
2927 }
2928 else /* TARGET_THUMB1 */
2929 {
2930 rtx tmp = force_reg (SImode, operands[2]);
2931 if (rtx_equal_p (operands[0], operands[1]))
2932 operands[2] = tmp;
2933 else
2934 {
2935 operands[2] = operands[1];
2936 operands[1] = tmp;
2937 }
2938 }
2939 }"
2940 )
2941
2942 (define_insn_and_split "*arm_xorsi3"
2943 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
2944 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
2945 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
2946 "TARGET_32BIT"
2947 "@
2948 eor%?\\t%0, %1, %2
2949 eor%?\\t%0, %1, %2
2950 eor%?\\t%0, %1, %2
2951 #"
2952 "TARGET_32BIT
2953 && CONST_INT_P (operands[2])
2954 && !const_ok_for_arm (INTVAL (operands[2]))"
2955 [(clobber (const_int 0))]
2956 {
2957 arm_split_constant (XOR, SImode, curr_insn,
2958 INTVAL (operands[2]), operands[0], operands[1], 0);
2959 DONE;
2960 }
2961 [(set_attr "length" "4,4,4,16")
2962 (set_attr "predicable" "yes")
2963 (set_attr "predicable_short_it" "no,yes,no,no")
2964 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
2965 )
2966
2967 (define_insn "*xorsi3_compare0"
2968 [(set (reg:CC_NOOV CC_REGNUM)
2969 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
2970 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
2971 (const_int 0)))
2972 (set (match_operand:SI 0 "s_register_operand" "=r,r")
2973 (xor:SI (match_dup 1) (match_dup 2)))]
2974 "TARGET_32BIT"
2975 "eors%?\\t%0, %1, %2"
2976 [(set_attr "conds" "set")
2977 (set_attr "type" "logics_imm,logics_reg")]
2978 )
2979
2980 (define_insn "*xorsi3_compare0_scratch"
2981 [(set (reg:CC_NOOV CC_REGNUM)
2982 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
2983 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
2984 (const_int 0)))]
2985 "TARGET_32BIT"
2986 "teq%?\\t%0, %1"
2987 [(set_attr "conds" "set")
2988 (set_attr "type" "logics_imm,logics_reg")]
2989 )
2990
2991 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2992 ; (NOT D) we can sometimes merge the final NOT into one of the following
2993 ; insns.
2994
2995 (define_split
2996 [(set (match_operand:SI 0 "s_register_operand" "")
2997 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2998 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2999 (match_operand:SI 3 "arm_rhs_operand" "")))
3000 (clobber (match_operand:SI 4 "s_register_operand" ""))]
3001 "TARGET_32BIT"
3002 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3003 (not:SI (match_dup 3))))
3004 (set (match_dup 0) (not:SI (match_dup 4)))]
3005 ""
3006 )
3007
3008 (define_insn_and_split "*andsi_iorsi3_notsi"
3009 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3010 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3011 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3012 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3013 "TARGET_32BIT"
3014 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3015 "&& reload_completed"
3016 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3017 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3018 {
3019 /* If operands[3] is a constant make sure to fold the NOT into it
3020 to avoid creating a NOT of a CONST_INT. */
3021 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3022 if (CONST_INT_P (not_rtx))
3023 {
3024 operands[4] = operands[0];
3025 operands[5] = not_rtx;
3026 }
3027 else
3028 {
3029 operands[5] = operands[0];
3030 operands[4] = not_rtx;
3031 }
3032 }
3033 [(set_attr "length" "8")
3034 (set_attr "ce_count" "2")
3035 (set_attr "predicable" "yes")
3036 (set_attr "type" "multiple")]
3037 )
3038
3039 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3040 ; insns are available?
3041 (define_split
3042 [(set (match_operand:SI 0 "s_register_operand" "")
3043 (match_operator:SI 1 "logical_binary_operator"
3044 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3045 (match_operand:SI 3 "const_int_operand" "")
3046 (match_operand:SI 4 "const_int_operand" ""))
3047 (match_operator:SI 9 "logical_binary_operator"
3048 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3049 (match_operand:SI 6 "const_int_operand" ""))
3050 (match_operand:SI 7 "s_register_operand" "")])]))
3051 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3052 "TARGET_32BIT
3053 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3054 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3055 [(set (match_dup 8)
3056 (match_op_dup 1
3057 [(ashift:SI (match_dup 2) (match_dup 4))
3058 (match_dup 5)]))
3059 (set (match_dup 0)
3060 (match_op_dup 1
3061 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3062 (match_dup 7)]))]
3063 "
3064 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3065 ")
3066
3067 (define_split
3068 [(set (match_operand:SI 0 "s_register_operand" "")
3069 (match_operator:SI 1 "logical_binary_operator"
3070 [(match_operator:SI 9 "logical_binary_operator"
3071 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3072 (match_operand:SI 6 "const_int_operand" ""))
3073 (match_operand:SI 7 "s_register_operand" "")])
3074 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3075 (match_operand:SI 3 "const_int_operand" "")
3076 (match_operand:SI 4 "const_int_operand" ""))]))
3077 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3078 "TARGET_32BIT
3079 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3080 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3081 [(set (match_dup 8)
3082 (match_op_dup 1
3083 [(ashift:SI (match_dup 2) (match_dup 4))
3084 (match_dup 5)]))
3085 (set (match_dup 0)
3086 (match_op_dup 1
3087 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3088 (match_dup 7)]))]
3089 "
3090 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3091 ")
3092
3093 (define_split
3094 [(set (match_operand:SI 0 "s_register_operand" "")
3095 (match_operator:SI 1 "logical_binary_operator"
3096 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3097 (match_operand:SI 3 "const_int_operand" "")
3098 (match_operand:SI 4 "const_int_operand" ""))
3099 (match_operator:SI 9 "logical_binary_operator"
3100 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3101 (match_operand:SI 6 "const_int_operand" ""))
3102 (match_operand:SI 7 "s_register_operand" "")])]))
3103 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3104 "TARGET_32BIT
3105 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3106 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3107 [(set (match_dup 8)
3108 (match_op_dup 1
3109 [(ashift:SI (match_dup 2) (match_dup 4))
3110 (match_dup 5)]))
3111 (set (match_dup 0)
3112 (match_op_dup 1
3113 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3114 (match_dup 7)]))]
3115 "
3116 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3117 ")
3118
3119 (define_split
3120 [(set (match_operand:SI 0 "s_register_operand" "")
3121 (match_operator:SI 1 "logical_binary_operator"
3122 [(match_operator:SI 9 "logical_binary_operator"
3123 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3124 (match_operand:SI 6 "const_int_operand" ""))
3125 (match_operand:SI 7 "s_register_operand" "")])
3126 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3127 (match_operand:SI 3 "const_int_operand" "")
3128 (match_operand:SI 4 "const_int_operand" ""))]))
3129 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3130 "TARGET_32BIT
3131 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3132 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3133 [(set (match_dup 8)
3134 (match_op_dup 1
3135 [(ashift:SI (match_dup 2) (match_dup 4))
3136 (match_dup 5)]))
3137 (set (match_dup 0)
3138 (match_op_dup 1
3139 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3140 (match_dup 7)]))]
3141 "
3142 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3143 ")
3144 \f
3145
3146 ;; Minimum and maximum insns
3147
3148 (define_expand "smaxsi3"
3149 [(parallel [
3150 (set (match_operand:SI 0 "s_register_operand")
3151 (smax:SI (match_operand:SI 1 "s_register_operand")
3152 (match_operand:SI 2 "arm_rhs_operand")))
3153 (clobber (reg:CC CC_REGNUM))])]
3154 "TARGET_32BIT"
3155 "
3156 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3157 {
3158 /* No need for a clobber of the condition code register here. */
3159 emit_insn (gen_rtx_SET (operands[0],
3160 gen_rtx_SMAX (SImode, operands[1],
3161 operands[2])));
3162 DONE;
3163 }
3164 ")
3165
3166 (define_insn "*smax_0"
3167 [(set (match_operand:SI 0 "s_register_operand" "=r")
3168 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3169 (const_int 0)))]
3170 "TARGET_32BIT"
3171 "bic%?\\t%0, %1, %1, asr #31"
3172 [(set_attr "predicable" "yes")
3173 (set_attr "type" "logic_shift_reg")]
3174 )
3175
3176 (define_insn "*smax_m1"
3177 [(set (match_operand:SI 0 "s_register_operand" "=r")
3178 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3179 (const_int -1)))]
3180 "TARGET_32BIT"
3181 "orr%?\\t%0, %1, %1, asr #31"
3182 [(set_attr "predicable" "yes")
3183 (set_attr "type" "logic_shift_reg")]
3184 )
3185
3186 (define_insn_and_split "*arm_smax_insn"
3187 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3188 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3189 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3190 (clobber (reg:CC CC_REGNUM))]
3191 "TARGET_ARM"
3192 "#"
3193 ; cmp\\t%1, %2\;movlt\\t%0, %2
3194 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3195 "TARGET_ARM"
3196 [(set (reg:CC CC_REGNUM)
3197 (compare:CC (match_dup 1) (match_dup 2)))
3198 (set (match_dup 0)
3199 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3200 (match_dup 1)
3201 (match_dup 2)))]
3202 ""
3203 [(set_attr "conds" "clob")
3204 (set_attr "length" "8,12")
3205 (set_attr "type" "multiple")]
3206 )
3207
3208 (define_expand "sminsi3"
3209 [(parallel [
3210 (set (match_operand:SI 0 "s_register_operand")
3211 (smin:SI (match_operand:SI 1 "s_register_operand")
3212 (match_operand:SI 2 "arm_rhs_operand")))
3213 (clobber (reg:CC CC_REGNUM))])]
3214 "TARGET_32BIT"
3215 "
3216 if (operands[2] == const0_rtx)
3217 {
3218 /* No need for a clobber of the condition code register here. */
3219 emit_insn (gen_rtx_SET (operands[0],
3220 gen_rtx_SMIN (SImode, operands[1],
3221 operands[2])));
3222 DONE;
3223 }
3224 ")
3225
3226 (define_insn "*smin_0"
3227 [(set (match_operand:SI 0 "s_register_operand" "=r")
3228 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3229 (const_int 0)))]
3230 "TARGET_32BIT"
3231 "and%?\\t%0, %1, %1, asr #31"
3232 [(set_attr "predicable" "yes")
3233 (set_attr "type" "logic_shift_reg")]
3234 )
3235
3236 (define_insn_and_split "*arm_smin_insn"
3237 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3238 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3239 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3240 (clobber (reg:CC CC_REGNUM))]
3241 "TARGET_ARM"
3242 "#"
3243 ; cmp\\t%1, %2\;movge\\t%0, %2
3244 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3245 "TARGET_ARM"
3246 [(set (reg:CC CC_REGNUM)
3247 (compare:CC (match_dup 1) (match_dup 2)))
3248 (set (match_dup 0)
3249 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3250 (match_dup 1)
3251 (match_dup 2)))]
3252 ""
3253 [(set_attr "conds" "clob")
3254 (set_attr "length" "8,12")
3255 (set_attr "type" "multiple,multiple")]
3256 )
3257
3258 (define_expand "umaxsi3"
3259 [(parallel [
3260 (set (match_operand:SI 0 "s_register_operand")
3261 (umax:SI (match_operand:SI 1 "s_register_operand")
3262 (match_operand:SI 2 "arm_rhs_operand")))
3263 (clobber (reg:CC CC_REGNUM))])]
3264 "TARGET_32BIT"
3265 ""
3266 )
3267
3268 (define_insn_and_split "*arm_umaxsi3"
3269 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3270 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3271 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3272 (clobber (reg:CC CC_REGNUM))]
3273 "TARGET_ARM"
3274 "#"
3275 ; cmp\\t%1, %2\;movcc\\t%0, %2
3276 ; cmp\\t%1, %2\;movcs\\t%0, %1
3277 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3278 "TARGET_ARM"
3279 [(set (reg:CC CC_REGNUM)
3280 (compare:CC (match_dup 1) (match_dup 2)))
3281 (set (match_dup 0)
3282 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3283 (match_dup 1)
3284 (match_dup 2)))]
3285 ""
3286 [(set_attr "conds" "clob")
3287 (set_attr "length" "8,8,12")
3288 (set_attr "type" "store_4")]
3289 )
3290
3291 (define_expand "uminsi3"
3292 [(parallel [
3293 (set (match_operand:SI 0 "s_register_operand")
3294 (umin:SI (match_operand:SI 1 "s_register_operand")
3295 (match_operand:SI 2 "arm_rhs_operand")))
3296 (clobber (reg:CC CC_REGNUM))])]
3297 "TARGET_32BIT"
3298 ""
3299 )
3300
3301 (define_insn_and_split "*arm_uminsi3"
3302 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3303 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3304 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3305 (clobber (reg:CC CC_REGNUM))]
3306 "TARGET_ARM"
3307 "#"
3308 ; cmp\\t%1, %2\;movcs\\t%0, %2
3309 ; cmp\\t%1, %2\;movcc\\t%0, %1
3310 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3311 "TARGET_ARM"
3312 [(set (reg:CC CC_REGNUM)
3313 (compare:CC (match_dup 1) (match_dup 2)))
3314 (set (match_dup 0)
3315 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3316 (match_dup 1)
3317 (match_dup 2)))]
3318 ""
3319 [(set_attr "conds" "clob")
3320 (set_attr "length" "8,8,12")
3321 (set_attr "type" "store_4")]
3322 )
3323
3324 (define_insn "*store_minmaxsi"
3325 [(set (match_operand:SI 0 "memory_operand" "=m")
3326 (match_operator:SI 3 "minmax_operator"
3327 [(match_operand:SI 1 "s_register_operand" "r")
3328 (match_operand:SI 2 "s_register_operand" "r")]))
3329 (clobber (reg:CC CC_REGNUM))]
3330 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
3331 "*
3332 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3333 operands[1], operands[2]);
3334 output_asm_insn (\"cmp\\t%1, %2\", operands);
3335 if (TARGET_THUMB2)
3336 output_asm_insn (\"ite\t%d3\", operands);
3337 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3338 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3339 return \"\";
3340 "
3341 [(set_attr "conds" "clob")
3342 (set (attr "length")
3343 (if_then_else (eq_attr "is_thumb" "yes")
3344 (const_int 14)
3345 (const_int 12)))
3346 (set_attr "type" "store_4")]
3347 )
3348
3349 ; Reject the frame pointer in operand[1], since reloading this after
3350 ; it has been eliminated can cause carnage.
3351 (define_insn "*minmax_arithsi"
3352 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3353 (match_operator:SI 4 "shiftable_operator"
3354 [(match_operator:SI 5 "minmax_operator"
3355 [(match_operand:SI 2 "s_register_operand" "r,r")
3356 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3357 (match_operand:SI 1 "s_register_operand" "0,?r")]))
3358 (clobber (reg:CC CC_REGNUM))]
3359 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
3360 "*
3361 {
3362 enum rtx_code code = GET_CODE (operands[4]);
3363 bool need_else;
3364
3365 if (which_alternative != 0 || operands[3] != const0_rtx
3366 || (code != PLUS && code != IOR && code != XOR))
3367 need_else = true;
3368 else
3369 need_else = false;
3370
3371 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3372 operands[2], operands[3]);
3373 output_asm_insn (\"cmp\\t%2, %3\", operands);
3374 if (TARGET_THUMB2)
3375 {
3376 if (need_else)
3377 output_asm_insn (\"ite\\t%d5\", operands);
3378 else
3379 output_asm_insn (\"it\\t%d5\", operands);
3380 }
3381 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3382 if (need_else)
3383 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3384 return \"\";
3385 }"
3386 [(set_attr "conds" "clob")
3387 (set (attr "length")
3388 (if_then_else (eq_attr "is_thumb" "yes")
3389 (const_int 14)
3390 (const_int 12)))
3391 (set_attr "type" "multiple")]
3392 )
3393
3394 ; Reject the frame pointer in operand[1], since reloading this after
3395 ; it has been eliminated can cause carnage.
3396 (define_insn_and_split "*minmax_arithsi_non_canon"
3397 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3398 (minus:SI
3399 (match_operand:SI 1 "s_register_operand" "0,?Ts")
3400 (match_operator:SI 4 "minmax_operator"
3401 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3402 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
3403 (clobber (reg:CC CC_REGNUM))]
3404 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3405 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
3406 "#"
3407 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3408 [(set (reg:CC CC_REGNUM)
3409 (compare:CC (match_dup 2) (match_dup 3)))
3410
3411 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3412 (set (match_dup 0)
3413 (minus:SI (match_dup 1)
3414 (match_dup 2))))
3415 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3416 (set (match_dup 0)
3417 (match_dup 6)))]
3418 {
3419 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3420 operands[2], operands[3]);
3421 enum rtx_code rc = minmax_code (operands[4]);
3422 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3423 operands[2], operands[3]);
3424
3425 if (mode == CCFPmode || mode == CCFPEmode)
3426 rc = reverse_condition_maybe_unordered (rc);
3427 else
3428 rc = reverse_condition (rc);
3429 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
3430 if (CONST_INT_P (operands[3]))
3431 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3432 else
3433 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
3434 }
3435 [(set_attr "conds" "clob")
3436 (set (attr "length")
3437 (if_then_else (eq_attr "is_thumb" "yes")
3438 (const_int 14)
3439 (const_int 12)))
3440 (set_attr "type" "multiple")]
3441 )
3442
3443 (define_code_iterator SAT [smin smax])
3444 (define_code_attr SATrev [(smin "smax") (smax "smin")])
3445 (define_code_attr SATlo [(smin "1") (smax "2")])
3446 (define_code_attr SAThi [(smin "2") (smax "1")])
3447
3448 (define_insn "*satsi_<SAT:code>"
3449 [(set (match_operand:SI 0 "s_register_operand" "=r")
3450 (SAT:SI (<SATrev>:SI (match_operand:SI 3 "s_register_operand" "r")
3451 (match_operand:SI 1 "const_int_operand" "i"))
3452 (match_operand:SI 2 "const_int_operand" "i")))]
3453 "TARGET_32BIT && arm_arch6
3454 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3455 {
3456 int mask;
3457 bool signed_sat;
3458 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3459 &mask, &signed_sat))
3460 gcc_unreachable ();
3461
3462 operands[1] = GEN_INT (mask);
3463 if (signed_sat)
3464 return "ssat%?\t%0, %1, %3";
3465 else
3466 return "usat%?\t%0, %1, %3";
3467 }
3468 [(set_attr "predicable" "yes")
3469 (set_attr "type" "alus_imm")]
3470 )
3471
3472 (define_insn "*satsi_<SAT:code>_shift"
3473 [(set (match_operand:SI 0 "s_register_operand" "=r")
3474 (SAT:SI (<SATrev>:SI (match_operator:SI 3 "sat_shift_operator"
3475 [(match_operand:SI 4 "s_register_operand" "r")
3476 (match_operand:SI 5 "const_int_operand" "i")])
3477 (match_operand:SI 1 "const_int_operand" "i"))
3478 (match_operand:SI 2 "const_int_operand" "i")))]
3479 "TARGET_32BIT && arm_arch6
3480 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3481 {
3482 int mask;
3483 bool signed_sat;
3484 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3485 &mask, &signed_sat))
3486 gcc_unreachable ();
3487
3488 operands[1] = GEN_INT (mask);
3489 if (signed_sat)
3490 return "ssat%?\t%0, %1, %4%S3";
3491 else
3492 return "usat%?\t%0, %1, %4%S3";
3493 }
3494 [(set_attr "predicable" "yes")
3495 (set_attr "shift" "3")
3496 (set_attr "type" "logic_shift_reg")])
3497 \f
3498 ;; Shift and rotation insns
3499
3500 (define_expand "ashldi3"
3501 [(set (match_operand:DI 0 "s_register_operand")
3502 (ashift:DI (match_operand:DI 1 "s_register_operand")
3503 (match_operand:SI 2 "reg_or_int_operand")))]
3504 "TARGET_32BIT"
3505 "
3506 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3507 operands[2], gen_reg_rtx (SImode),
3508 gen_reg_rtx (SImode));
3509 DONE;
3510 ")
3511
3512 (define_expand "ashlsi3"
3513 [(set (match_operand:SI 0 "s_register_operand")
3514 (ashift:SI (match_operand:SI 1 "s_register_operand")
3515 (match_operand:SI 2 "arm_rhs_operand")))]
3516 "TARGET_EITHER"
3517 "
3518 if (CONST_INT_P (operands[2])
3519 && (UINTVAL (operands[2])) > 31)
3520 {
3521 emit_insn (gen_movsi (operands[0], const0_rtx));
3522 DONE;
3523 }
3524 "
3525 )
3526
3527 (define_expand "ashrdi3"
3528 [(set (match_operand:DI 0 "s_register_operand")
3529 (ashiftrt:DI (match_operand:DI 1 "s_register_operand")
3530 (match_operand:SI 2 "reg_or_int_operand")))]
3531 "TARGET_32BIT"
3532 "
3533 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3534 operands[2], gen_reg_rtx (SImode),
3535 gen_reg_rtx (SImode));
3536 DONE;
3537 ")
3538
3539 (define_expand "ashrsi3"
3540 [(set (match_operand:SI 0 "s_register_operand")
3541 (ashiftrt:SI (match_operand:SI 1 "s_register_operand")
3542 (match_operand:SI 2 "arm_rhs_operand")))]
3543 "TARGET_EITHER"
3544 "
3545 if (CONST_INT_P (operands[2])
3546 && UINTVAL (operands[2]) > 31)
3547 operands[2] = GEN_INT (31);
3548 "
3549 )
3550
3551 (define_expand "lshrdi3"
3552 [(set (match_operand:DI 0 "s_register_operand")
3553 (lshiftrt:DI (match_operand:DI 1 "s_register_operand")
3554 (match_operand:SI 2 "reg_or_int_operand")))]
3555 "TARGET_32BIT"
3556 "
3557 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3558 operands[2], gen_reg_rtx (SImode),
3559 gen_reg_rtx (SImode));
3560 DONE;
3561 ")
3562
3563 (define_expand "lshrsi3"
3564 [(set (match_operand:SI 0 "s_register_operand")
3565 (lshiftrt:SI (match_operand:SI 1 "s_register_operand")
3566 (match_operand:SI 2 "arm_rhs_operand")))]
3567 "TARGET_EITHER"
3568 "
3569 if (CONST_INT_P (operands[2])
3570 && (UINTVAL (operands[2])) > 31)
3571 {
3572 emit_insn (gen_movsi (operands[0], const0_rtx));
3573 DONE;
3574 }
3575 "
3576 )
3577
3578 (define_expand "rotlsi3"
3579 [(set (match_operand:SI 0 "s_register_operand")
3580 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3581 (match_operand:SI 2 "reg_or_int_operand")))]
3582 "TARGET_32BIT"
3583 "
3584 if (CONST_INT_P (operands[2]))
3585 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3586 else
3587 {
3588 rtx reg = gen_reg_rtx (SImode);
3589 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3590 operands[2] = reg;
3591 }
3592 "
3593 )
3594
3595 (define_expand "rotrsi3"
3596 [(set (match_operand:SI 0 "s_register_operand")
3597 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3598 (match_operand:SI 2 "arm_rhs_operand")))]
3599 "TARGET_EITHER"
3600 "
3601 if (TARGET_32BIT)
3602 {
3603 if (CONST_INT_P (operands[2])
3604 && UINTVAL (operands[2]) > 31)
3605 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3606 }
3607 else /* TARGET_THUMB1 */
3608 {
3609 if (CONST_INT_P (operands [2]))
3610 operands [2] = force_reg (SImode, operands[2]);
3611 }
3612 "
3613 )
3614
3615 (define_insn "*arm_shiftsi3"
3616 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
3617 (match_operator:SI 3 "shift_operator"
3618 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3619 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
3620 "TARGET_32BIT"
3621 "* return arm_output_shift(operands, 0);"
3622 [(set_attr "predicable" "yes")
3623 (set_attr "arch" "t2,t2,*,*")
3624 (set_attr "predicable_short_it" "yes,yes,no,no")
3625 (set_attr "length" "4")
3626 (set_attr "shift" "1")
3627 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
3628 )
3629
3630 (define_insn "*shiftsi3_compare0"
3631 [(set (reg:CC_NOOV CC_REGNUM)
3632 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3633 [(match_operand:SI 1 "s_register_operand" "r,r")
3634 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
3635 (const_int 0)))
3636 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3637 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3638 "TARGET_32BIT"
3639 "* return arm_output_shift(operands, 1);"
3640 [(set_attr "conds" "set")
3641 (set_attr "shift" "1")
3642 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
3643 )
3644
3645 (define_insn "*shiftsi3_compare0_scratch"
3646 [(set (reg:CC_NOOV CC_REGNUM)
3647 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3648 [(match_operand:SI 1 "s_register_operand" "r,r")
3649 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
3650 (const_int 0)))
3651 (clobber (match_scratch:SI 0 "=r,r"))]
3652 "TARGET_32BIT"
3653 "* return arm_output_shift(operands, 1);"
3654 [(set_attr "conds" "set")
3655 (set_attr "shift" "1")
3656 (set_attr "type" "shift_imm,shift_reg")]
3657 )
3658
3659 (define_insn "*not_shiftsi"
3660 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3661 (not:SI (match_operator:SI 3 "shift_operator"
3662 [(match_operand:SI 1 "s_register_operand" "r,r")
3663 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3664 "TARGET_32BIT"
3665 "mvn%?\\t%0, %1%S3"
3666 [(set_attr "predicable" "yes")
3667 (set_attr "shift" "1")
3668 (set_attr "arch" "32,a")
3669 (set_attr "type" "mvn_shift,mvn_shift_reg")])
3670
3671 (define_insn "*not_shiftsi_compare0"
3672 [(set (reg:CC_NOOV CC_REGNUM)
3673 (compare:CC_NOOV
3674 (not:SI (match_operator:SI 3 "shift_operator"
3675 [(match_operand:SI 1 "s_register_operand" "r,r")
3676 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3677 (const_int 0)))
3678 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3679 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3680 "TARGET_32BIT"
3681 "mvns%?\\t%0, %1%S3"
3682 [(set_attr "conds" "set")
3683 (set_attr "shift" "1")
3684 (set_attr "arch" "32,a")
3685 (set_attr "type" "mvn_shift,mvn_shift_reg")])
3686
3687 (define_insn "*not_shiftsi_compare0_scratch"
3688 [(set (reg:CC_NOOV CC_REGNUM)
3689 (compare:CC_NOOV
3690 (not:SI (match_operator:SI 3 "shift_operator"
3691 [(match_operand:SI 1 "s_register_operand" "r,r")
3692 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3693 (const_int 0)))
3694 (clobber (match_scratch:SI 0 "=r,r"))]
3695 "TARGET_32BIT"
3696 "mvns%?\\t%0, %1%S3"
3697 [(set_attr "conds" "set")
3698 (set_attr "shift" "1")
3699 (set_attr "arch" "32,a")
3700 (set_attr "type" "mvn_shift,mvn_shift_reg")])
3701
3702 ;; We don't really have extzv, but defining this using shifts helps
3703 ;; to reduce register pressure later on.
3704
3705 (define_expand "extzv"
3706 [(set (match_operand 0 "s_register_operand")
3707 (zero_extract (match_operand 1 "nonimmediate_operand")
3708 (match_operand 2 "const_int_operand")
3709 (match_operand 3 "const_int_operand")))]
3710 "TARGET_THUMB1 || arm_arch_thumb2"
3711 "
3712 {
3713 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3714 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3715
3716 if (arm_arch_thumb2)
3717 {
3718 HOST_WIDE_INT width = INTVAL (operands[2]);
3719 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3720
3721 if (unaligned_access && MEM_P (operands[1])
3722 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3723 {
3724 rtx base_addr;
3725
3726 if (BYTES_BIG_ENDIAN)
3727 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3728 - bitpos;
3729
3730 if (width == 32)
3731 {
3732 base_addr = adjust_address (operands[1], SImode,
3733 bitpos / BITS_PER_UNIT);
3734 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3735 }
3736 else
3737 {
3738 rtx dest = operands[0];
3739 rtx tmp = gen_reg_rtx (SImode);
3740
3741 /* We may get a paradoxical subreg here. Strip it off. */
3742 if (GET_CODE (dest) == SUBREG
3743 && GET_MODE (dest) == SImode
3744 && GET_MODE (SUBREG_REG (dest)) == HImode)
3745 dest = SUBREG_REG (dest);
3746
3747 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3748 FAIL;
3749
3750 base_addr = adjust_address (operands[1], HImode,
3751 bitpos / BITS_PER_UNIT);
3752 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3753 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3754 }
3755 DONE;
3756 }
3757 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3758 {
3759 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3760 operands[3]));
3761 DONE;
3762 }
3763 else
3764 FAIL;
3765 }
3766
3767 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3768 FAIL;
3769
3770 operands[3] = GEN_INT (rshift);
3771
3772 if (lshift == 0)
3773 {
3774 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3775 DONE;
3776 }
3777
3778 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3779 operands[3], gen_reg_rtx (SImode)));
3780 DONE;
3781 }"
3782 )
3783
3784 ;; Helper for extzv, for the Thumb-1 register-shifts case.
3785
3786 (define_expand "extzv_t1"
3787 [(set (match_operand:SI 4 "s_register_operand")
3788 (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
3789 (match_operand:SI 2 "const_int_operand")))
3790 (set (match_operand:SI 0 "s_register_operand")
3791 (lshiftrt:SI (match_dup 4)
3792 (match_operand:SI 3 "const_int_operand")))]
3793 "TARGET_THUMB1"
3794 "")
3795
3796 (define_expand "extv"
3797 [(set (match_operand 0 "s_register_operand")
3798 (sign_extract (match_operand 1 "nonimmediate_operand")
3799 (match_operand 2 "const_int_operand")
3800 (match_operand 3 "const_int_operand")))]
3801 "arm_arch_thumb2"
3802 {
3803 HOST_WIDE_INT width = INTVAL (operands[2]);
3804 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3805
3806 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3807 && (bitpos % BITS_PER_UNIT) == 0)
3808 {
3809 rtx base_addr;
3810
3811 if (BYTES_BIG_ENDIAN)
3812 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3813
3814 if (width == 32)
3815 {
3816 base_addr = adjust_address (operands[1], SImode,
3817 bitpos / BITS_PER_UNIT);
3818 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3819 }
3820 else
3821 {
3822 rtx dest = operands[0];
3823 rtx tmp = gen_reg_rtx (SImode);
3824
3825 /* We may get a paradoxical subreg here. Strip it off. */
3826 if (GET_CODE (dest) == SUBREG
3827 && GET_MODE (dest) == SImode
3828 && GET_MODE (SUBREG_REG (dest)) == HImode)
3829 dest = SUBREG_REG (dest);
3830
3831 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3832 FAIL;
3833
3834 base_addr = adjust_address (operands[1], HImode,
3835 bitpos / BITS_PER_UNIT);
3836 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3837 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3838 }
3839
3840 DONE;
3841 }
3842 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3843 FAIL;
3844 else if (GET_MODE (operands[0]) == SImode
3845 && GET_MODE (operands[1]) == SImode)
3846 {
3847 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3848 operands[3]));
3849 DONE;
3850 }
3851
3852 FAIL;
3853 })
3854
3855 ; Helper to expand register forms of extv with the proper modes.
3856
3857 (define_expand "extv_regsi"
3858 [(set (match_operand:SI 0 "s_register_operand")
3859 (sign_extract:SI (match_operand:SI 1 "s_register_operand")
3860 (match_operand 2 "const_int_operand")
3861 (match_operand 3 "const_int_operand")))]
3862 ""
3863 {
3864 })
3865
3866 ; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3867
3868 (define_insn "unaligned_loaddi"
3869 [(set (match_operand:DI 0 "s_register_operand" "=r")
3870 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")]
3871 UNSPEC_UNALIGNED_LOAD))]
3872 "TARGET_32BIT && TARGET_LDRD"
3873 "*
3874 return output_move_double (operands, true, NULL);
3875 "
3876 [(set_attr "length" "8")
3877 (set_attr "type" "load_8")])
3878
3879 (define_insn "unaligned_loadsi"
3880 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
3881 (unspec:SI [(match_operand:SI 1 "memory_operand" "m,Uw,m")]
3882 UNSPEC_UNALIGNED_LOAD))]
3883 "unaligned_access"
3884 "@
3885 ldr\t%0, %1\t@ unaligned
3886 ldr%?\t%0, %1\t@ unaligned
3887 ldr%?\t%0, %1\t@ unaligned"
3888 [(set_attr "arch" "t1,t2,32")
3889 (set_attr "length" "2,2,4")
3890 (set_attr "predicable" "no,yes,yes")
3891 (set_attr "predicable_short_it" "no,yes,no")
3892 (set_attr "type" "load_4")])
3893
3894 ;; The 16-bit Thumb1 variant of ldrsh requires two registers in the
3895 ;; address (there's no immediate format). That's tricky to support
3896 ;; here and we don't really need this pattern for that case, so only
3897 ;; enable for 32-bit ISAs.
3898 (define_insn "unaligned_loadhis"
3899 [(set (match_operand:SI 0 "s_register_operand" "=r")
3900 (sign_extend:SI
3901 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
3902 UNSPEC_UNALIGNED_LOAD)))]
3903 "unaligned_access && TARGET_32BIT"
3904 "ldrsh%?\t%0, %1\t@ unaligned"
3905 [(set_attr "predicable" "yes")
3906 (set_attr "type" "load_byte")])
3907
3908 (define_insn "unaligned_loadhiu"
3909 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
3910 (zero_extend:SI
3911 (unspec:HI [(match_operand:HI 1 "memory_operand" "m,Uw,m")]
3912 UNSPEC_UNALIGNED_LOAD)))]
3913 "unaligned_access"
3914 "@
3915 ldrh\t%0, %1\t@ unaligned
3916 ldrh%?\t%0, %1\t@ unaligned
3917 ldrh%?\t%0, %1\t@ unaligned"
3918 [(set_attr "arch" "t1,t2,32")
3919 (set_attr "length" "2,2,4")
3920 (set_attr "predicable" "no,yes,yes")
3921 (set_attr "predicable_short_it" "no,yes,no")
3922 (set_attr "type" "load_byte")])
3923
3924 (define_insn "unaligned_storedi"
3925 [(set (match_operand:DI 0 "memory_operand" "=m")
3926 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
3927 UNSPEC_UNALIGNED_STORE))]
3928 "TARGET_32BIT && TARGET_LDRD"
3929 "*
3930 return output_move_double (operands, true, NULL);
3931 "
3932 [(set_attr "length" "8")
3933 (set_attr "type" "store_8")])
3934
3935 (define_insn "unaligned_storesi"
3936 [(set (match_operand:SI 0 "memory_operand" "=m,Uw,m")
3937 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,l,r")]
3938 UNSPEC_UNALIGNED_STORE))]
3939 "unaligned_access"
3940 "@
3941 str\t%1, %0\t@ unaligned
3942 str%?\t%1, %0\t@ unaligned
3943 str%?\t%1, %0\t@ unaligned"
3944 [(set_attr "arch" "t1,t2,32")
3945 (set_attr "length" "2,2,4")
3946 (set_attr "predicable" "no,yes,yes")
3947 (set_attr "predicable_short_it" "no,yes,no")
3948 (set_attr "type" "store_4")])
3949
3950 (define_insn "unaligned_storehi"
3951 [(set (match_operand:HI 0 "memory_operand" "=m,Uw,m")
3952 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,l,r")]
3953 UNSPEC_UNALIGNED_STORE))]
3954 "unaligned_access"
3955 "@
3956 strh\t%1, %0\t@ unaligned
3957 strh%?\t%1, %0\t@ unaligned
3958 strh%?\t%1, %0\t@ unaligned"
3959 [(set_attr "arch" "t1,t2,32")
3960 (set_attr "length" "2,2,4")
3961 (set_attr "predicable" "no,yes,yes")
3962 (set_attr "predicable_short_it" "no,yes,no")
3963 (set_attr "type" "store_4")])
3964
3965
3966 (define_insn "*extv_reg"
3967 [(set (match_operand:SI 0 "s_register_operand" "=r")
3968 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3969 (match_operand:SI 2 "const_int_operand" "n")
3970 (match_operand:SI 3 "const_int_operand" "n")))]
3971 "arm_arch_thumb2
3972 && IN_RANGE (INTVAL (operands[3]), 0, 31)
3973 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
3974 "sbfx%?\t%0, %1, %3, %2"
3975 [(set_attr "length" "4")
3976 (set_attr "predicable" "yes")
3977 (set_attr "type" "bfm")]
3978 )
3979
3980 (define_insn "extzv_t2"
3981 [(set (match_operand:SI 0 "s_register_operand" "=r")
3982 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3983 (match_operand:SI 2 "const_int_operand" "n")
3984 (match_operand:SI 3 "const_int_operand" "n")))]
3985 "arm_arch_thumb2
3986 && IN_RANGE (INTVAL (operands[3]), 0, 31)
3987 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
3988 "ubfx%?\t%0, %1, %3, %2"
3989 [(set_attr "length" "4")
3990 (set_attr "predicable" "yes")
3991 (set_attr "type" "bfm")]
3992 )
3993
3994
3995 ;; Division instructions
3996 (define_insn "divsi3"
3997 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3998 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
3999 (match_operand:SI 2 "s_register_operand" "r,r")))]
4000 "TARGET_IDIV"
4001 "@
4002 sdiv%?\t%0, %1, %2
4003 sdiv\t%0, %1, %2"
4004 [(set_attr "arch" "32,v8mb")
4005 (set_attr "predicable" "yes")
4006 (set_attr "type" "sdiv")]
4007 )
4008
4009 (define_insn "udivsi3"
4010 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4011 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4012 (match_operand:SI 2 "s_register_operand" "r,r")))]
4013 "TARGET_IDIV"
4014 "@
4015 udiv%?\t%0, %1, %2
4016 udiv\t%0, %1, %2"
4017 [(set_attr "arch" "32,v8mb")
4018 (set_attr "predicable" "yes")
4019 (set_attr "type" "udiv")]
4020 )
4021
4022 \f
4023 ;; Unary arithmetic insns
4024
4025 (define_expand "negvsi3"
4026 [(match_operand:SI 0 "register_operand")
4027 (match_operand:SI 1 "register_operand")
4028 (match_operand 2 "")]
4029 "TARGET_32BIT"
4030 {
4031 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4032 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4033
4034 DONE;
4035 })
4036
4037 (define_expand "negvdi3"
4038 [(match_operand:DI 0 "register_operand")
4039 (match_operand:DI 1 "register_operand")
4040 (match_operand 2 "")]
4041 "TARGET_ARM"
4042 {
4043 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4044 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4045
4046 DONE;
4047 })
4048
4049
4050 (define_insn_and_split "negdi2_compare"
4051 [(set (reg:CC CC_REGNUM)
4052 (compare:CC
4053 (const_int 0)
4054 (match_operand:DI 1 "register_operand" "0,r")))
4055 (set (match_operand:DI 0 "register_operand" "=r,&r")
4056 (minus:DI (const_int 0) (match_dup 1)))]
4057 "TARGET_ARM"
4058 "#"
4059 "&& reload_completed"
4060 [(parallel [(set (reg:CC CC_REGNUM)
4061 (compare:CC (const_int 0) (match_dup 1)))
4062 (set (match_dup 0) (minus:SI (const_int 0)
4063 (match_dup 1)))])
4064 (parallel [(set (reg:CC CC_REGNUM)
4065 (compare:CC (const_int 0) (match_dup 3)))
4066 (set (match_dup 2)
4067 (minus:SI
4068 (minus:SI (const_int 0) (match_dup 3))
4069 (ltu:SI (reg:CC CC_REGNUM)
4070 (const_int 0))))])]
4071 {
4072 operands[2] = gen_highpart (SImode, operands[0]);
4073 operands[0] = gen_lowpart (SImode, operands[0]);
4074 operands[3] = gen_highpart (SImode, operands[1]);
4075 operands[1] = gen_lowpart (SImode, operands[1]);
4076 }
4077 [(set_attr "conds" "set")
4078 (set_attr "length" "8")
4079 (set_attr "type" "multiple")]
4080 )
4081
4082 (define_expand "negdi2"
4083 [(parallel
4084 [(set (match_operand:DI 0 "s_register_operand")
4085 (neg:DI (match_operand:DI 1 "s_register_operand")))
4086 (clobber (reg:CC CC_REGNUM))])]
4087 "TARGET_EITHER"
4088 )
4089
4090 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
4091 ;; The first alternative allows the common case of a *full* overlap.
4092 (define_insn_and_split "*negdi2_insn"
4093 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4094 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
4095 (clobber (reg:CC CC_REGNUM))]
4096 "TARGET_32BIT"
4097 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4098 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
4099 "TARGET_32BIT"
4100 [(parallel [(set (reg:CC CC_REGNUM)
4101 (compare:CC (const_int 0) (match_dup 1)))
4102 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4103 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4104 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
4105 {
4106 operands[2] = gen_highpart (SImode, operands[0]);
4107 operands[0] = gen_lowpart (SImode, operands[0]);
4108 operands[3] = gen_highpart (SImode, operands[1]);
4109 operands[1] = gen_lowpart (SImode, operands[1]);
4110 }
4111 [(set_attr "conds" "clob")
4112 (set_attr "length" "8")
4113 (set_attr "type" "multiple")]
4114 )
4115
4116 (define_insn "*negsi2_carryin_compare"
4117 [(set (reg:CC CC_REGNUM)
4118 (compare:CC (const_int 0)
4119 (match_operand:SI 1 "s_register_operand" "r")))
4120 (set (match_operand:SI 0 "s_register_operand" "=r")
4121 (minus:SI (minus:SI (const_int 0)
4122 (match_dup 1))
4123 (match_operand:SI 2 "arm_borrow_operation" "")))]
4124 "TARGET_ARM"
4125 "rscs\\t%0, %1, #0"
4126 [(set_attr "conds" "set")
4127 (set_attr "type" "alus_imm")]
4128 )
4129
4130 (define_expand "negsi2"
4131 [(set (match_operand:SI 0 "s_register_operand")
4132 (neg:SI (match_operand:SI 1 "s_register_operand")))]
4133 "TARGET_EITHER"
4134 ""
4135 )
4136
4137 (define_insn "*arm_negsi2"
4138 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4139 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
4140 "TARGET_32BIT"
4141 "rsb%?\\t%0, %1, #0"
4142 [(set_attr "predicable" "yes")
4143 (set_attr "predicable_short_it" "yes,no")
4144 (set_attr "arch" "t2,*")
4145 (set_attr "length" "4")
4146 (set_attr "type" "alu_sreg")]
4147 )
4148
4149 (define_expand "negsf2"
4150 [(set (match_operand:SF 0 "s_register_operand")
4151 (neg:SF (match_operand:SF 1 "s_register_operand")))]
4152 "TARGET_32BIT && TARGET_HARD_FLOAT"
4153 ""
4154 )
4155
4156 (define_expand "negdf2"
4157 [(set (match_operand:DF 0 "s_register_operand")
4158 (neg:DF (match_operand:DF 1 "s_register_operand")))]
4159 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
4160 "")
4161
4162 (define_insn_and_split "*zextendsidi_negsi"
4163 [(set (match_operand:DI 0 "s_register_operand" "=r")
4164 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4165 "TARGET_32BIT"
4166 "#"
4167 ""
4168 [(set (match_dup 2)
4169 (neg:SI (match_dup 1)))
4170 (set (match_dup 3)
4171 (const_int 0))]
4172 {
4173 operands[2] = gen_lowpart (SImode, operands[0]);
4174 operands[3] = gen_highpart (SImode, operands[0]);
4175 }
4176 [(set_attr "length" "8")
4177 (set_attr "type" "multiple")]
4178 )
4179
4180 ;; Negate an extended 32-bit value.
4181 (define_insn_and_split "*negdi_extendsidi"
4182 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4183 (neg:DI (sign_extend:DI
4184 (match_operand:SI 1 "s_register_operand" "l,r"))))
4185 (clobber (reg:CC CC_REGNUM))]
4186 "TARGET_32BIT"
4187 "#"
4188 "&& reload_completed"
4189 [(const_int 0)]
4190 {
4191 rtx low = gen_lowpart (SImode, operands[0]);
4192 rtx high = gen_highpart (SImode, operands[0]);
4193
4194 if (reg_overlap_mentioned_p (low, operands[1]))
4195 {
4196 /* Input overlaps the low word of the output. Use:
4197 asr Rhi, Rin, #31
4198 rsbs Rlo, Rin, #0
4199 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4200 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
4201
4202 emit_insn (gen_rtx_SET (high,
4203 gen_rtx_ASHIFTRT (SImode, operands[1],
4204 GEN_INT (31))));
4205
4206 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4207 if (TARGET_ARM)
4208 emit_insn (gen_rtx_SET (high,
4209 gen_rtx_MINUS (SImode,
4210 gen_rtx_MINUS (SImode,
4211 const0_rtx,
4212 high),
4213 gen_rtx_LTU (SImode,
4214 cc_reg,
4215 const0_rtx))));
4216 else
4217 {
4218 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4219 emit_insn (gen_rtx_SET (high,
4220 gen_rtx_MINUS (SImode,
4221 gen_rtx_MINUS (SImode,
4222 high,
4223 two_x),
4224 gen_rtx_LTU (SImode,
4225 cc_reg,
4226 const0_rtx))));
4227 }
4228 }
4229 else
4230 {
4231 /* No overlap, or overlap on high word. Use:
4232 rsb Rlo, Rin, #0
4233 bic Rhi, Rlo, Rin
4234 asr Rhi, Rhi, #31
4235 Flags not needed for this sequence. */
4236 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4237 emit_insn (gen_rtx_SET (high,
4238 gen_rtx_AND (SImode,
4239 gen_rtx_NOT (SImode, operands[1]),
4240 low)));
4241 emit_insn (gen_rtx_SET (high,
4242 gen_rtx_ASHIFTRT (SImode, high,
4243 GEN_INT (31))));
4244 }
4245 DONE;
4246 }
4247 [(set_attr "length" "12")
4248 (set_attr "arch" "t2,*")
4249 (set_attr "type" "multiple")]
4250 )
4251
4252 (define_insn_and_split "*negdi_zero_extendsidi"
4253 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4254 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4255 (clobber (reg:CC CC_REGNUM))]
4256 "TARGET_32BIT"
4257 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4258 ;; Don't care what register is input to sbc,
4259 ;; since we just need to propagate the carry.
4260 "&& reload_completed"
4261 [(parallel [(set (reg:CC CC_REGNUM)
4262 (compare:CC (const_int 0) (match_dup 1)))
4263 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4264 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4265 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
4266 {
4267 operands[2] = gen_highpart (SImode, operands[0]);
4268 operands[0] = gen_lowpart (SImode, operands[0]);
4269 }
4270 [(set_attr "conds" "clob")
4271 (set_attr "length" "8")
4272 (set_attr "type" "multiple")] ;; length in thumb is 4
4273 )
4274
4275 ;; abssi2 doesn't really clobber the condition codes if a different register
4276 ;; is being set. To keep things simple, assume during rtl manipulations that
4277 ;; it does, but tell the final scan operator the truth. Similarly for
4278 ;; (neg (abs...))
4279
4280 (define_expand "abssi2"
4281 [(parallel
4282 [(set (match_operand:SI 0 "s_register_operand")
4283 (abs:SI (match_operand:SI 1 "s_register_operand")))
4284 (clobber (match_dup 2))])]
4285 "TARGET_EITHER"
4286 "
4287 if (TARGET_THUMB1)
4288 operands[2] = gen_rtx_SCRATCH (SImode);
4289 else
4290 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4291 ")
4292
4293 (define_insn_and_split "*arm_abssi2"
4294 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4295 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
4296 (clobber (reg:CC CC_REGNUM))]
4297 "TARGET_ARM"
4298 "#"
4299 "&& reload_completed"
4300 [(const_int 0)]
4301 {
4302 /* if (which_alternative == 0) */
4303 if (REGNO(operands[0]) == REGNO(operands[1]))
4304 {
4305 /* Emit the pattern:
4306 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4307 [(set (reg:CC CC_REGNUM)
4308 (compare:CC (match_dup 0) (const_int 0)))
4309 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4310 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4311 */
4312 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4313 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4314 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4315 (gen_rtx_LT (SImode,
4316 gen_rtx_REG (CCmode, CC_REGNUM),
4317 const0_rtx)),
4318 (gen_rtx_SET (operands[0],
4319 (gen_rtx_MINUS (SImode,
4320 const0_rtx,
4321 operands[1]))))));
4322 DONE;
4323 }
4324 else
4325 {
4326 /* Emit the pattern:
4327 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4328 [(set (match_dup 0)
4329 (xor:SI (match_dup 1)
4330 (ashiftrt:SI (match_dup 1) (const_int 31))))
4331 (set (match_dup 0)
4332 (minus:SI (match_dup 0)
4333 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4334 */
4335 emit_insn (gen_rtx_SET (operands[0],
4336 gen_rtx_XOR (SImode,
4337 gen_rtx_ASHIFTRT (SImode,
4338 operands[1],
4339 GEN_INT (31)),
4340 operands[1])));
4341 emit_insn (gen_rtx_SET (operands[0],
4342 gen_rtx_MINUS (SImode,
4343 operands[0],
4344 gen_rtx_ASHIFTRT (SImode,
4345 operands[1],
4346 GEN_INT (31)))));
4347 DONE;
4348 }
4349 }
4350 [(set_attr "conds" "clob,*")
4351 (set_attr "shift" "1")
4352 (set_attr "predicable" "no, yes")
4353 (set_attr "length" "8")
4354 (set_attr "type" "multiple")]
4355 )
4356
4357 (define_insn_and_split "*arm_neg_abssi2"
4358 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4359 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
4360 (clobber (reg:CC CC_REGNUM))]
4361 "TARGET_ARM"
4362 "#"
4363 "&& reload_completed"
4364 [(const_int 0)]
4365 {
4366 /* if (which_alternative == 0) */
4367 if (REGNO (operands[0]) == REGNO (operands[1]))
4368 {
4369 /* Emit the pattern:
4370 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4371 */
4372 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4373 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4374 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4375 gen_rtx_GT (SImode,
4376 gen_rtx_REG (CCmode, CC_REGNUM),
4377 const0_rtx),
4378 gen_rtx_SET (operands[0],
4379 (gen_rtx_MINUS (SImode,
4380 const0_rtx,
4381 operands[1])))));
4382 }
4383 else
4384 {
4385 /* Emit the pattern:
4386 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4387 */
4388 emit_insn (gen_rtx_SET (operands[0],
4389 gen_rtx_XOR (SImode,
4390 gen_rtx_ASHIFTRT (SImode,
4391 operands[1],
4392 GEN_INT (31)),
4393 operands[1])));
4394 emit_insn (gen_rtx_SET (operands[0],
4395 gen_rtx_MINUS (SImode,
4396 gen_rtx_ASHIFTRT (SImode,
4397 operands[1],
4398 GEN_INT (31)),
4399 operands[0])));
4400 }
4401 DONE;
4402 }
4403 [(set_attr "conds" "clob,*")
4404 (set_attr "shift" "1")
4405 (set_attr "predicable" "no, yes")
4406 (set_attr "length" "8")
4407 (set_attr "type" "multiple")]
4408 )
4409
4410 (define_expand "abssf2"
4411 [(set (match_operand:SF 0 "s_register_operand")
4412 (abs:SF (match_operand:SF 1 "s_register_operand")))]
4413 "TARGET_32BIT && TARGET_HARD_FLOAT"
4414 "")
4415
4416 (define_expand "absdf2"
4417 [(set (match_operand:DF 0 "s_register_operand")
4418 (abs:DF (match_operand:DF 1 "s_register_operand")))]
4419 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4420 "")
4421
4422 (define_expand "sqrtsf2"
4423 [(set (match_operand:SF 0 "s_register_operand")
4424 (sqrt:SF (match_operand:SF 1 "s_register_operand")))]
4425 "TARGET_32BIT && TARGET_HARD_FLOAT"
4426 "")
4427
4428 (define_expand "sqrtdf2"
4429 [(set (match_operand:DF 0 "s_register_operand")
4430 (sqrt:DF (match_operand:DF 1 "s_register_operand")))]
4431 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
4432 "")
4433
4434 (define_expand "one_cmplsi2"
4435 [(set (match_operand:SI 0 "s_register_operand")
4436 (not:SI (match_operand:SI 1 "s_register_operand")))]
4437 "TARGET_EITHER"
4438 ""
4439 )
4440
4441 (define_insn "*arm_one_cmplsi2"
4442 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4443 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
4444 "TARGET_32BIT"
4445 "mvn%?\\t%0, %1"
4446 [(set_attr "predicable" "yes")
4447 (set_attr "predicable_short_it" "yes,no")
4448 (set_attr "arch" "t2,*")
4449 (set_attr "length" "4")
4450 (set_attr "type" "mvn_reg")]
4451 )
4452
4453 (define_insn "*notsi_compare0"
4454 [(set (reg:CC_NOOV CC_REGNUM)
4455 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4456 (const_int 0)))
4457 (set (match_operand:SI 0 "s_register_operand" "=r")
4458 (not:SI (match_dup 1)))]
4459 "TARGET_32BIT"
4460 "mvns%?\\t%0, %1"
4461 [(set_attr "conds" "set")
4462 (set_attr "type" "mvn_reg")]
4463 )
4464
4465 (define_insn "*notsi_compare0_scratch"
4466 [(set (reg:CC_NOOV CC_REGNUM)
4467 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4468 (const_int 0)))
4469 (clobber (match_scratch:SI 0 "=r"))]
4470 "TARGET_32BIT"
4471 "mvns%?\\t%0, %1"
4472 [(set_attr "conds" "set")
4473 (set_attr "type" "mvn_reg")]
4474 )
4475 \f
4476 ;; Fixed <--> Floating conversion insns
4477
4478 (define_expand "floatsihf2"
4479 [(set (match_operand:HF 0 "general_operand")
4480 (float:HF (match_operand:SI 1 "general_operand")))]
4481 "TARGET_EITHER"
4482 "
4483 {
4484 rtx op1 = gen_reg_rtx (SFmode);
4485 expand_float (op1, operands[1], 0);
4486 op1 = convert_to_mode (HFmode, op1, 0);
4487 emit_move_insn (operands[0], op1);
4488 DONE;
4489 }"
4490 )
4491
4492 (define_expand "floatdihf2"
4493 [(set (match_operand:HF 0 "general_operand")
4494 (float:HF (match_operand:DI 1 "general_operand")))]
4495 "TARGET_EITHER"
4496 "
4497 {
4498 rtx op1 = gen_reg_rtx (SFmode);
4499 expand_float (op1, operands[1], 0);
4500 op1 = convert_to_mode (HFmode, op1, 0);
4501 emit_move_insn (operands[0], op1);
4502 DONE;
4503 }"
4504 )
4505
4506 (define_expand "floatsisf2"
4507 [(set (match_operand:SF 0 "s_register_operand")
4508 (float:SF (match_operand:SI 1 "s_register_operand")))]
4509 "TARGET_32BIT && TARGET_HARD_FLOAT"
4510 "
4511 ")
4512
4513 (define_expand "floatsidf2"
4514 [(set (match_operand:DF 0 "s_register_operand")
4515 (float:DF (match_operand:SI 1 "s_register_operand")))]
4516 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4517 "
4518 ")
4519
4520 (define_expand "fix_trunchfsi2"
4521 [(set (match_operand:SI 0 "general_operand")
4522 (fix:SI (fix:HF (match_operand:HF 1 "general_operand"))))]
4523 "TARGET_EITHER"
4524 "
4525 {
4526 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4527 expand_fix (operands[0], op1, 0);
4528 DONE;
4529 }"
4530 )
4531
4532 (define_expand "fix_trunchfdi2"
4533 [(set (match_operand:DI 0 "general_operand")
4534 (fix:DI (fix:HF (match_operand:HF 1 "general_operand"))))]
4535 "TARGET_EITHER"
4536 "
4537 {
4538 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4539 expand_fix (operands[0], op1, 0);
4540 DONE;
4541 }"
4542 )
4543
4544 (define_expand "fix_truncsfsi2"
4545 [(set (match_operand:SI 0 "s_register_operand")
4546 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"))))]
4547 "TARGET_32BIT && TARGET_HARD_FLOAT"
4548 "
4549 ")
4550
4551 (define_expand "fix_truncdfsi2"
4552 [(set (match_operand:SI 0 "s_register_operand")
4553 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"))))]
4554 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4555 "
4556 ")
4557
4558 ;; Truncation insns
4559
4560 (define_expand "truncdfsf2"
4561 [(set (match_operand:SF 0 "s_register_operand")
4562 (float_truncate:SF
4563 (match_operand:DF 1 "s_register_operand")))]
4564 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4565 ""
4566 )
4567
4568 ;; DFmode to HFmode conversions on targets without a single-step hardware
4569 ;; instruction for it would have to go through SFmode. This is dangerous
4570 ;; as it introduces double rounding.
4571 ;;
4572 ;; Disable this pattern unless we are in an unsafe math mode, or we have
4573 ;; a single-step instruction.
4574
4575 (define_expand "truncdfhf2"
4576 [(set (match_operand:HF 0 "s_register_operand")
4577 (float_truncate:HF
4578 (match_operand:DF 1 "s_register_operand")))]
4579 "(TARGET_EITHER && flag_unsafe_math_optimizations)
4580 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
4581 {
4582 /* We don't have a direct instruction for this, so we must be in
4583 an unsafe math mode, and going via SFmode. */
4584
4585 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
4586 {
4587 rtx op1;
4588 op1 = convert_to_mode (SFmode, operands[1], 0);
4589 op1 = convert_to_mode (HFmode, op1, 0);
4590 emit_move_insn (operands[0], op1);
4591 DONE;
4592 }
4593 /* Otherwise, we will pick this up as a single instruction with
4594 no intermediary rounding. */
4595 }
4596 )
4597 \f
4598 ;; Zero and sign extension instructions.
4599
4600 (define_insn "zero_extend<mode>di2"
4601 [(set (match_operand:DI 0 "s_register_operand" "=r,?r")
4602 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4603 "<qhs_zextenddi_cstr>")))]
4604 "TARGET_32BIT <qhs_zextenddi_cond>"
4605 "#"
4606 [(set_attr "length" "4,8")
4607 (set_attr "arch" "*,*")
4608 (set_attr "ce_count" "2")
4609 (set_attr "predicable" "yes")
4610 (set_attr "type" "mov_reg,multiple")]
4611 )
4612
4613 (define_insn "extend<mode>di2"
4614 [(set (match_operand:DI 0 "s_register_operand" "=r,?r,?r")
4615 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4616 "<qhs_extenddi_cstr>")))]
4617 "TARGET_32BIT <qhs_sextenddi_cond>"
4618 "#"
4619 [(set_attr "length" "4,8,8")
4620 (set_attr "ce_count" "2")
4621 (set_attr "shift" "1")
4622 (set_attr "predicable" "yes")
4623 (set_attr "arch" "*,a,t")
4624 (set_attr "type" "mov_reg,multiple,multiple")]
4625 )
4626
4627 ;; Splits for all extensions to DImode
4628 (define_split
4629 [(set (match_operand:DI 0 "s_register_operand" "")
4630 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4631 "TARGET_32BIT"
4632 [(set (match_dup 0) (match_dup 1))]
4633 {
4634 rtx lo_part = gen_lowpart (SImode, operands[0]);
4635 machine_mode src_mode = GET_MODE (operands[1]);
4636
4637 if (src_mode == SImode)
4638 emit_move_insn (lo_part, operands[1]);
4639 else
4640 emit_insn (gen_rtx_SET (lo_part,
4641 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4642 operands[0] = gen_highpart (SImode, operands[0]);
4643 operands[1] = const0_rtx;
4644 })
4645
4646 (define_split
4647 [(set (match_operand:DI 0 "s_register_operand" "")
4648 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4649 "TARGET_32BIT"
4650 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4651 {
4652 rtx lo_part = gen_lowpart (SImode, operands[0]);
4653 machine_mode src_mode = GET_MODE (operands[1]);
4654
4655 if (src_mode == SImode)
4656 emit_move_insn (lo_part, operands[1]);
4657 else
4658 emit_insn (gen_rtx_SET (lo_part,
4659 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4660 operands[1] = lo_part;
4661 operands[0] = gen_highpart (SImode, operands[0]);
4662 })
4663
4664 (define_expand "zero_extendhisi2"
4665 [(set (match_operand:SI 0 "s_register_operand")
4666 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
4667 "TARGET_EITHER"
4668 {
4669 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4670 {
4671 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4672 DONE;
4673 }
4674 if (!arm_arch6 && !MEM_P (operands[1]))
4675 {
4676 rtx t = gen_lowpart (SImode, operands[1]);
4677 rtx tmp = gen_reg_rtx (SImode);
4678 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4679 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4680 DONE;
4681 }
4682 })
4683
4684 (define_split
4685 [(set (match_operand:SI 0 "s_register_operand" "")
4686 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
4687 "!TARGET_THUMB2 && !arm_arch6"
4688 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4689 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4690 {
4691 operands[2] = gen_lowpart (SImode, operands[1]);
4692 })
4693
4694 (define_insn "*arm_zero_extendhisi2"
4695 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4696 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4697 "TARGET_ARM && arm_arch4 && !arm_arch6"
4698 "@
4699 #
4700 ldrh%?\\t%0, %1"
4701 [(set_attr "type" "alu_shift_reg,load_byte")
4702 (set_attr "predicable" "yes")]
4703 )
4704
4705 (define_insn "*arm_zero_extendhisi2_v6"
4706 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4707 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
4708 "TARGET_ARM && arm_arch6"
4709 "@
4710 uxth%?\\t%0, %1
4711 ldrh%?\\t%0, %1"
4712 [(set_attr "predicable" "yes")
4713 (set_attr "type" "extend,load_byte")]
4714 )
4715
4716 (define_insn "*arm_zero_extendhisi2addsi"
4717 [(set (match_operand:SI 0 "s_register_operand" "=r")
4718 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4719 (match_operand:SI 2 "s_register_operand" "r")))]
4720 "TARGET_INT_SIMD"
4721 "uxtah%?\\t%0, %2, %1"
4722 [(set_attr "type" "alu_shift_reg")
4723 (set_attr "predicable" "yes")]
4724 )
4725
4726 (define_expand "zero_extendqisi2"
4727 [(set (match_operand:SI 0 "s_register_operand")
4728 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
4729 "TARGET_EITHER"
4730 {
4731 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
4732 {
4733 emit_insn (gen_andsi3 (operands[0],
4734 gen_lowpart (SImode, operands[1]),
4735 GEN_INT (255)));
4736 DONE;
4737 }
4738 if (!arm_arch6 && !MEM_P (operands[1]))
4739 {
4740 rtx t = gen_lowpart (SImode, operands[1]);
4741 rtx tmp = gen_reg_rtx (SImode);
4742 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4743 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4744 DONE;
4745 }
4746 })
4747
4748 (define_split
4749 [(set (match_operand:SI 0 "s_register_operand" "")
4750 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
4751 "!arm_arch6"
4752 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4753 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4754 {
4755 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4756 if (TARGET_ARM)
4757 {
4758 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4759 DONE;
4760 }
4761 })
4762
4763 (define_insn "*arm_zero_extendqisi2"
4764 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4765 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4766 "TARGET_ARM && !arm_arch6"
4767 "@
4768 #
4769 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
4770 [(set_attr "length" "8,4")
4771 (set_attr "type" "alu_shift_reg,load_byte")
4772 (set_attr "predicable" "yes")]
4773 )
4774
4775 (define_insn "*arm_zero_extendqisi2_v6"
4776 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4777 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
4778 "TARGET_ARM && arm_arch6"
4779 "@
4780 uxtb%?\\t%0, %1
4781 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
4782 [(set_attr "type" "extend,load_byte")
4783 (set_attr "predicable" "yes")]
4784 )
4785
4786 (define_insn "*arm_zero_extendqisi2addsi"
4787 [(set (match_operand:SI 0 "s_register_operand" "=r")
4788 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4789 (match_operand:SI 2 "s_register_operand" "r")))]
4790 "TARGET_INT_SIMD"
4791 "uxtab%?\\t%0, %2, %1"
4792 [(set_attr "predicable" "yes")
4793 (set_attr "type" "alu_shift_reg")]
4794 )
4795
4796 (define_split
4797 [(set (match_operand:SI 0 "s_register_operand" "")
4798 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4799 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4800 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
4801 [(set (match_dup 2) (match_dup 1))
4802 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4803 ""
4804 )
4805
4806 (define_split
4807 [(set (match_operand:SI 0 "s_register_operand" "")
4808 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4809 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4810 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
4811 [(set (match_dup 2) (match_dup 1))
4812 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4813 ""
4814 )
4815
4816
4817 (define_split
4818 [(set (match_operand:SI 0 "s_register_operand" "")
4819 (IOR_XOR:SI (and:SI (ashift:SI
4820 (match_operand:SI 1 "s_register_operand" "")
4821 (match_operand:SI 2 "const_int_operand" ""))
4822 (match_operand:SI 3 "const_int_operand" ""))
4823 (zero_extend:SI
4824 (match_operator 5 "subreg_lowpart_operator"
4825 [(match_operand:SI 4 "s_register_operand" "")]))))]
4826 "TARGET_32BIT
4827 && (UINTVAL (operands[3])
4828 == (GET_MODE_MASK (GET_MODE (operands[5]))
4829 & (GET_MODE_MASK (GET_MODE (operands[5]))
4830 << (INTVAL (operands[2])))))"
4831 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
4832 (match_dup 4)))
4833 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4834 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4835 )
4836
4837 (define_insn "*compareqi_eq0"
4838 [(set (reg:CC_Z CC_REGNUM)
4839 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4840 (const_int 0)))]
4841 "TARGET_32BIT"
4842 "tst%?\\t%0, #255"
4843 [(set_attr "conds" "set")
4844 (set_attr "predicable" "yes")
4845 (set_attr "type" "logic_imm")]
4846 )
4847
4848 (define_expand "extendhisi2"
4849 [(set (match_operand:SI 0 "s_register_operand")
4850 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
4851 "TARGET_EITHER"
4852 {
4853 if (TARGET_THUMB1)
4854 {
4855 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4856 DONE;
4857 }
4858 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4859 {
4860 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4861 DONE;
4862 }
4863
4864 if (!arm_arch6 && !MEM_P (operands[1]))
4865 {
4866 rtx t = gen_lowpart (SImode, operands[1]);
4867 rtx tmp = gen_reg_rtx (SImode);
4868 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4869 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4870 DONE;
4871 }
4872 })
4873
4874 (define_split
4875 [(parallel
4876 [(set (match_operand:SI 0 "register_operand" "")
4877 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4878 (clobber (match_scratch:SI 2 ""))])]
4879 "!arm_arch6"
4880 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4881 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4882 {
4883 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4884 })
4885
4886 ;; This pattern will only be used when ldsh is not available
4887 (define_expand "extendhisi2_mem"
4888 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4889 (set (match_dup 3)
4890 (zero_extend:SI (match_dup 7)))
4891 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4892 (set (match_operand:SI 0 "" "")
4893 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4894 "TARGET_ARM"
4895 "
4896 {
4897 rtx mem1, mem2;
4898 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4899
4900 mem1 = change_address (operands[1], QImode, addr);
4901 mem2 = change_address (operands[1], QImode,
4902 plus_constant (Pmode, addr, 1));
4903 operands[0] = gen_lowpart (SImode, operands[0]);
4904 operands[1] = mem1;
4905 operands[2] = gen_reg_rtx (SImode);
4906 operands[3] = gen_reg_rtx (SImode);
4907 operands[6] = gen_reg_rtx (SImode);
4908 operands[7] = mem2;
4909
4910 if (BYTES_BIG_ENDIAN)
4911 {
4912 operands[4] = operands[2];
4913 operands[5] = operands[3];
4914 }
4915 else
4916 {
4917 operands[4] = operands[3];
4918 operands[5] = operands[2];
4919 }
4920 }"
4921 )
4922
4923 (define_split
4924 [(set (match_operand:SI 0 "register_operand" "")
4925 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4926 "!arm_arch6"
4927 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4928 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4929 {
4930 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4931 })
4932
4933 (define_insn "*arm_extendhisi2"
4934 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4935 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
4936 "TARGET_ARM && arm_arch4 && !arm_arch6"
4937 "@
4938 #
4939 ldrsh%?\\t%0, %1"
4940 [(set_attr "length" "8,4")
4941 (set_attr "type" "alu_shift_reg,load_byte")
4942 (set_attr "predicable" "yes")]
4943 )
4944
4945 ;; ??? Check Thumb-2 pool range
4946 (define_insn "*arm_extendhisi2_v6"
4947 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4948 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
4949 "TARGET_32BIT && arm_arch6"
4950 "@
4951 sxth%?\\t%0, %1
4952 ldrsh%?\\t%0, %1"
4953 [(set_attr "type" "extend,load_byte")
4954 (set_attr "predicable" "yes")]
4955 )
4956
4957 (define_insn "*arm_extendhisi2addsi"
4958 [(set (match_operand:SI 0 "s_register_operand" "=r")
4959 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4960 (match_operand:SI 2 "s_register_operand" "r")))]
4961 "TARGET_INT_SIMD"
4962 "sxtah%?\\t%0, %2, %1"
4963 [(set_attr "type" "alu_shift_reg")]
4964 )
4965
4966 (define_expand "extendqihi2"
4967 [(set (match_dup 2)
4968 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")
4969 (const_int 24)))
4970 (set (match_operand:HI 0 "s_register_operand")
4971 (ashiftrt:SI (match_dup 2)
4972 (const_int 24)))]
4973 "TARGET_ARM"
4974 "
4975 {
4976 if (arm_arch4 && MEM_P (operands[1]))
4977 {
4978 emit_insn (gen_rtx_SET (operands[0],
4979 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4980 DONE;
4981 }
4982 if (!s_register_operand (operands[1], QImode))
4983 operands[1] = copy_to_mode_reg (QImode, operands[1]);
4984 operands[0] = gen_lowpart (SImode, operands[0]);
4985 operands[1] = gen_lowpart (SImode, operands[1]);
4986 operands[2] = gen_reg_rtx (SImode);
4987 }"
4988 )
4989
4990 (define_insn "*arm_extendqihi_insn"
4991 [(set (match_operand:HI 0 "s_register_operand" "=r")
4992 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4993 "TARGET_ARM && arm_arch4"
4994 "ldrsb%?\\t%0, %1"
4995 [(set_attr "type" "load_byte")
4996 (set_attr "predicable" "yes")]
4997 )
4998
4999 (define_expand "extendqisi2"
5000 [(set (match_operand:SI 0 "s_register_operand")
5001 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")))]
5002 "TARGET_EITHER"
5003 {
5004 if (!arm_arch4 && MEM_P (operands[1]))
5005 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5006
5007 if (!arm_arch6 && !MEM_P (operands[1]))
5008 {
5009 rtx t = gen_lowpart (SImode, operands[1]);
5010 rtx tmp = gen_reg_rtx (SImode);
5011 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5012 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5013 DONE;
5014 }
5015 })
5016
5017 (define_split
5018 [(set (match_operand:SI 0 "register_operand" "")
5019 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5020 "!arm_arch6"
5021 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5022 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5023 {
5024 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5025 })
5026
5027 (define_insn "*arm_extendqisi"
5028 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5029 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5030 "TARGET_ARM && arm_arch4 && !arm_arch6"
5031 "@
5032 #
5033 ldrsb%?\\t%0, %1"
5034 [(set_attr "length" "8,4")
5035 (set_attr "type" "alu_shift_reg,load_byte")
5036 (set_attr "predicable" "yes")]
5037 )
5038
5039 (define_insn "*arm_extendqisi_v6"
5040 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5041 (sign_extend:SI
5042 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5043 "TARGET_ARM && arm_arch6"
5044 "@
5045 sxtb%?\\t%0, %1
5046 ldrsb%?\\t%0, %1"
5047 [(set_attr "type" "extend,load_byte")
5048 (set_attr "predicable" "yes")]
5049 )
5050
5051 (define_insn "*arm_extendqisi2addsi"
5052 [(set (match_operand:SI 0 "s_register_operand" "=r")
5053 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5054 (match_operand:SI 2 "s_register_operand" "r")))]
5055 "TARGET_INT_SIMD"
5056 "sxtab%?\\t%0, %2, %1"
5057 [(set_attr "type" "alu_shift_reg")
5058 (set_attr "predicable" "yes")]
5059 )
5060
5061 (define_insn "arm_<sup>xtb16"
5062 [(set (match_operand:SI 0 "s_register_operand" "=r")
5063 (unspec:SI
5064 [(match_operand:SI 1 "s_register_operand" "r")] USXTB16))]
5065 "TARGET_INT_SIMD"
5066 "<sup>xtb16%?\\t%0, %1"
5067 [(set_attr "predicable" "yes")
5068 (set_attr "type" "alu_dsp_reg")])
5069
5070 (define_insn "arm_<simd32_op>"
5071 [(set (match_operand:SI 0 "s_register_operand" "=r")
5072 (unspec:SI
5073 [(match_operand:SI 1 "s_register_operand" "r")
5074 (match_operand:SI 2 "s_register_operand" "r")] SIMD32_NOGE_BINOP))]
5075 "TARGET_INT_SIMD"
5076 "<simd32_op>%?\\t%0, %1, %2"
5077 [(set_attr "predicable" "yes")
5078 (set_attr "type" "alu_dsp_reg")])
5079
5080 (define_insn "arm_usada8"
5081 [(set (match_operand:SI 0 "s_register_operand" "=r")
5082 (unspec:SI
5083 [(match_operand:SI 1 "s_register_operand" "r")
5084 (match_operand:SI 2 "s_register_operand" "r")
5085 (match_operand:SI 3 "s_register_operand" "r")] UNSPEC_USADA8))]
5086 "TARGET_INT_SIMD"
5087 "usada8%?\\t%0, %1, %2, %3"
5088 [(set_attr "predicable" "yes")
5089 (set_attr "type" "alu_dsp_reg")])
5090
5091 (define_insn "arm_<simd32_op>"
5092 [(set (match_operand:DI 0 "s_register_operand" "=r")
5093 (unspec:DI
5094 [(match_operand:SI 1 "s_register_operand" "r")
5095 (match_operand:SI 2 "s_register_operand" "r")
5096 (match_operand:DI 3 "s_register_operand" "0")] SIMD32_DIMODE))]
5097 "TARGET_INT_SIMD"
5098 "<simd32_op>%?\\t%Q0, %R0, %1, %2"
5099 [(set_attr "predicable" "yes")
5100 (set_attr "type" "smlald")])
5101
5102 (define_expand "extendsfdf2"
5103 [(set (match_operand:DF 0 "s_register_operand")
5104 (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
5105 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5106 ""
5107 )
5108
5109 ;; HFmode -> DFmode conversions where we don't have an instruction for it
5110 ;; must go through SFmode.
5111 ;;
5112 ;; This is always safe for an extend.
5113
5114 (define_expand "extendhfdf2"
5115 [(set (match_operand:DF 0 "s_register_operand")
5116 (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
5117 "TARGET_EITHER"
5118 {
5119 /* We don't have a direct instruction for this, so go via SFmode. */
5120 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5121 {
5122 rtx op1;
5123 op1 = convert_to_mode (SFmode, operands[1], 0);
5124 op1 = convert_to_mode (DFmode, op1, 0);
5125 emit_insn (gen_movdf (operands[0], op1));
5126 DONE;
5127 }
5128 /* Otherwise, we're done producing RTL and will pick up the correct
5129 pattern to do this with one rounding-step in a single instruction. */
5130 }
5131 )
5132 \f
5133 ;; Move insns (including loads and stores)
5134
5135 ;; XXX Just some ideas about movti.
5136 ;; I don't think these are a good idea on the arm, there just aren't enough
5137 ;; registers
5138 ;;(define_expand "loadti"
5139 ;; [(set (match_operand:TI 0 "s_register_operand")
5140 ;; (mem:TI (match_operand:SI 1 "address_operand")))]
5141 ;; "" "")
5142
5143 ;;(define_expand "storeti"
5144 ;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
5145 ;; (match_operand:TI 1 "s_register_operand"))]
5146 ;; "" "")
5147
5148 ;;(define_expand "movti"
5149 ;; [(set (match_operand:TI 0 "general_operand")
5150 ;; (match_operand:TI 1 "general_operand"))]
5151 ;; ""
5152 ;; "
5153 ;;{
5154 ;; rtx insn;
5155 ;;
5156 ;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
5157 ;; operands[1] = copy_to_reg (operands[1]);
5158 ;; if (MEM_P (operands[0]))
5159 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5160 ;; else if (MEM_P (operands[1]))
5161 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5162 ;; else
5163 ;; FAIL;
5164 ;;
5165 ;; emit_insn (insn);
5166 ;; DONE;
5167 ;;}")
5168
5169 ;; Recognize garbage generated above.
5170
5171 ;;(define_insn ""
5172 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5173 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5174 ;; ""
5175 ;; "*
5176 ;; {
5177 ;; register mem = (which_alternative < 3);
5178 ;; register const char *template;
5179 ;;
5180 ;; operands[mem] = XEXP (operands[mem], 0);
5181 ;; switch (which_alternative)
5182 ;; {
5183 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5184 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5185 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5186 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5187 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5188 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
5189 ;; }
5190 ;; output_asm_insn (template, operands);
5191 ;; return \"\";
5192 ;; }")
5193
5194 (define_expand "movdi"
5195 [(set (match_operand:DI 0 "general_operand")
5196 (match_operand:DI 1 "general_operand"))]
5197 "TARGET_EITHER"
5198 "
5199 gcc_checking_assert (aligned_operand (operands[0], DImode));
5200 gcc_checking_assert (aligned_operand (operands[1], DImode));
5201 if (can_create_pseudo_p ())
5202 {
5203 if (!REG_P (operands[0]))
5204 operands[1] = force_reg (DImode, operands[1]);
5205 }
5206 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
5207 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
5208 {
5209 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5210 when expanding function calls. */
5211 gcc_assert (can_create_pseudo_p ());
5212 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5213 {
5214 /* Perform load into legal reg pair first, then move. */
5215 rtx reg = gen_reg_rtx (DImode);
5216 emit_insn (gen_movdi (reg, operands[1]));
5217 operands[1] = reg;
5218 }
5219 emit_move_insn (gen_lowpart (SImode, operands[0]),
5220 gen_lowpart (SImode, operands[1]));
5221 emit_move_insn (gen_highpart (SImode, operands[0]),
5222 gen_highpart (SImode, operands[1]));
5223 DONE;
5224 }
5225 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
5226 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
5227 {
5228 /* Avoid STRD's from an odd-numbered register pair in ARM state
5229 when expanding function prologue. */
5230 gcc_assert (can_create_pseudo_p ());
5231 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5232 ? gen_reg_rtx (DImode)
5233 : operands[0];
5234 emit_move_insn (gen_lowpart (SImode, split_dest),
5235 gen_lowpart (SImode, operands[1]));
5236 emit_move_insn (gen_highpart (SImode, split_dest),
5237 gen_highpart (SImode, operands[1]));
5238 if (split_dest != operands[0])
5239 emit_insn (gen_movdi (operands[0], split_dest));
5240 DONE;
5241 }
5242 "
5243 )
5244
5245 (define_insn "*arm_movdi"
5246 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5247 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
5248 "TARGET_32BIT
5249 && !(TARGET_HARD_FLOAT)
5250 && !TARGET_IWMMXT
5251 && ( register_operand (operands[0], DImode)
5252 || register_operand (operands[1], DImode))"
5253 "*
5254 switch (which_alternative)
5255 {
5256 case 0:
5257 case 1:
5258 case 2:
5259 return \"#\";
5260 case 3:
5261 /* Cannot load it directly, split to load it via MOV / MOVT. */
5262 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5263 return \"#\";
5264 /* Fall through. */
5265 default:
5266 return output_move_double (operands, true, NULL);
5267 }
5268 "
5269 [(set_attr "length" "8,12,16,8,8")
5270 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
5271 (set_attr "arm_pool_range" "*,*,*,1020,*")
5272 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5273 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
5274 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5275 )
5276
5277 (define_split
5278 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5279 (match_operand:ANY64 1 "immediate_operand" ""))]
5280 "TARGET_32BIT
5281 && reload_completed
5282 && (arm_disable_literal_pool
5283 || (arm_const_double_inline_cost (operands[1])
5284 <= arm_max_const_double_inline_cost ()))"
5285 [(const_int 0)]
5286 "
5287 arm_split_constant (SET, SImode, curr_insn,
5288 INTVAL (gen_lowpart (SImode, operands[1])),
5289 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5290 arm_split_constant (SET, SImode, curr_insn,
5291 INTVAL (gen_highpart_mode (SImode,
5292 GET_MODE (operands[0]),
5293 operands[1])),
5294 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5295 DONE;
5296 "
5297 )
5298
5299 ; If optimizing for size, or if we have load delay slots, then
5300 ; we want to split the constant into two separate operations.
5301 ; In both cases this may split a trivial part into a single data op
5302 ; leaving a single complex constant to load. We can also get longer
5303 ; offsets in a LDR which means we get better chances of sharing the pool
5304 ; entries. Finally, we can normally do a better job of scheduling
5305 ; LDR instructions than we can with LDM.
5306 ; This pattern will only match if the one above did not.
5307 (define_split
5308 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5309 (match_operand:ANY64 1 "const_double_operand" ""))]
5310 "TARGET_ARM && reload_completed
5311 && arm_const_double_by_parts (operands[1])"
5312 [(set (match_dup 0) (match_dup 1))
5313 (set (match_dup 2) (match_dup 3))]
5314 "
5315 operands[2] = gen_highpart (SImode, operands[0]);
5316 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5317 operands[1]);
5318 operands[0] = gen_lowpart (SImode, operands[0]);
5319 operands[1] = gen_lowpart (SImode, operands[1]);
5320 "
5321 )
5322
5323 (define_split
5324 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5325 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5326 "TARGET_EITHER && reload_completed"
5327 [(set (match_dup 0) (match_dup 1))
5328 (set (match_dup 2) (match_dup 3))]
5329 "
5330 operands[2] = gen_highpart (SImode, operands[0]);
5331 operands[3] = gen_highpart (SImode, operands[1]);
5332 operands[0] = gen_lowpart (SImode, operands[0]);
5333 operands[1] = gen_lowpart (SImode, operands[1]);
5334
5335 /* Handle a partial overlap. */
5336 if (rtx_equal_p (operands[0], operands[3]))
5337 {
5338 rtx tmp0 = operands[0];
5339 rtx tmp1 = operands[1];
5340
5341 operands[0] = operands[2];
5342 operands[1] = operands[3];
5343 operands[2] = tmp0;
5344 operands[3] = tmp1;
5345 }
5346 "
5347 )
5348
5349 ;; We can't actually do base+index doubleword loads if the index and
5350 ;; destination overlap. Split here so that we at least have chance to
5351 ;; schedule.
5352 (define_split
5353 [(set (match_operand:DI 0 "s_register_operand" "")
5354 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5355 (match_operand:SI 2 "s_register_operand" ""))))]
5356 "TARGET_LDRD
5357 && reg_overlap_mentioned_p (operands[0], operands[1])
5358 && reg_overlap_mentioned_p (operands[0], operands[2])"
5359 [(set (match_dup 4)
5360 (plus:SI (match_dup 1)
5361 (match_dup 2)))
5362 (set (match_dup 0)
5363 (mem:DI (match_dup 4)))]
5364 "
5365 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5366 "
5367 )
5368
5369 (define_expand "movsi"
5370 [(set (match_operand:SI 0 "general_operand")
5371 (match_operand:SI 1 "general_operand"))]
5372 "TARGET_EITHER"
5373 "
5374 {
5375 rtx base, offset, tmp;
5376
5377 gcc_checking_assert (aligned_operand (operands[0], SImode));
5378 gcc_checking_assert (aligned_operand (operands[1], SImode));
5379 if (TARGET_32BIT || TARGET_HAVE_MOVT)
5380 {
5381 /* Everything except mem = const or mem = mem can be done easily. */
5382 if (MEM_P (operands[0]))
5383 operands[1] = force_reg (SImode, operands[1]);
5384 if (arm_general_register_operand (operands[0], SImode)
5385 && CONST_INT_P (operands[1])
5386 && !(const_ok_for_arm (INTVAL (operands[1]))
5387 || const_ok_for_arm (~INTVAL (operands[1]))))
5388 {
5389 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5390 {
5391 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5392 DONE;
5393 }
5394 else
5395 {
5396 arm_split_constant (SET, SImode, NULL_RTX,
5397 INTVAL (operands[1]), operands[0], NULL_RTX,
5398 optimize && can_create_pseudo_p ());
5399 DONE;
5400 }
5401 }
5402 }
5403 else /* Target doesn't have MOVT... */
5404 {
5405 if (can_create_pseudo_p ())
5406 {
5407 if (!REG_P (operands[0]))
5408 operands[1] = force_reg (SImode, operands[1]);
5409 }
5410 }
5411
5412 split_const (operands[1], &base, &offset);
5413 if (INTVAL (offset) != 0
5414 && targetm.cannot_force_const_mem (SImode, operands[1]))
5415 {
5416 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5417 emit_move_insn (tmp, base);
5418 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5419 DONE;
5420 }
5421
5422 tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
5423
5424 /* Recognize the case where operand[1] is a reference to thread-local
5425 data and load its address to a register. Offsets have been split off
5426 already. */
5427 if (arm_tls_referenced_p (operands[1]))
5428 operands[1] = legitimize_tls_address (operands[1], tmp);
5429 else if (flag_pic
5430 && (CONSTANT_P (operands[1])
5431 || symbol_mentioned_p (operands[1])
5432 || label_mentioned_p (operands[1])))
5433 operands[1] =
5434 legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
5435 }
5436 "
5437 )
5438
5439 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5440 ;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5441 ;; so this does not matter.
5442 (define_insn "*arm_movt"
5443 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
5444 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
5445 (match_operand:SI 2 "general_operand" "i,i")))]
5446 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
5447 "@
5448 movt%?\t%0, #:upper16:%c2
5449 movt\t%0, #:upper16:%c2"
5450 [(set_attr "arch" "32,v8mb")
5451 (set_attr "predicable" "yes")
5452 (set_attr "length" "4")
5453 (set_attr "type" "alu_sreg")]
5454 )
5455
5456 (define_insn "*arm_movsi_insn"
5457 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5458 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
5459 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
5460 && ( register_operand (operands[0], SImode)
5461 || register_operand (operands[1], SImode))"
5462 "@
5463 mov%?\\t%0, %1
5464 mov%?\\t%0, %1
5465 mvn%?\\t%0, #%B1
5466 movw%?\\t%0, %1
5467 ldr%?\\t%0, %1
5468 str%?\\t%1, %0"
5469 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
5470 (set_attr "predicable" "yes")
5471 (set_attr "arch" "*,*,*,v6t2,*,*")
5472 (set_attr "pool_range" "*,*,*,*,4096,*")
5473 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5474 )
5475
5476 (define_split
5477 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5478 (match_operand:SI 1 "const_int_operand" ""))]
5479 "(TARGET_32BIT || TARGET_HAVE_MOVT)
5480 && (!(const_ok_for_arm (INTVAL (operands[1]))
5481 || const_ok_for_arm (~INTVAL (operands[1]))))"
5482 [(clobber (const_int 0))]
5483 "
5484 arm_split_constant (SET, SImode, NULL_RTX,
5485 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5486 DONE;
5487 "
5488 )
5489
5490 ;; A normal way to do (symbol + offset) requires three instructions at least
5491 ;; (depends on how big the offset is) as below:
5492 ;; movw r0, #:lower16:g
5493 ;; movw r0, #:upper16:g
5494 ;; adds r0, #4
5495 ;;
5496 ;; A better way would be:
5497 ;; movw r0, #:lower16:g+4
5498 ;; movw r0, #:upper16:g+4
5499 ;;
5500 ;; The limitation of this way is that the length of offset should be a 16-bit
5501 ;; signed value, because current assembler only supports REL type relocation for
5502 ;; such case. If the more powerful RELA type is supported in future, we should
5503 ;; update this pattern to go with better way.
5504 (define_split
5505 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5506 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5507 (match_operand:SI 2 "const_int_operand" ""))))]
5508 "TARGET_THUMB
5509 && TARGET_HAVE_MOVT
5510 && arm_disable_literal_pool
5511 && reload_completed
5512 && GET_CODE (operands[1]) == SYMBOL_REF"
5513 [(clobber (const_int 0))]
5514 "
5515 int offset = INTVAL (operands[2]);
5516
5517 if (offset < -0x8000 || offset > 0x7fff)
5518 {
5519 arm_emit_movpair (operands[0], operands[1]);
5520 emit_insn (gen_rtx_SET (operands[0],
5521 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5522 }
5523 else
5524 {
5525 rtx op = gen_rtx_CONST (SImode,
5526 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5527 arm_emit_movpair (operands[0], op);
5528 }
5529 "
5530 )
5531
5532 ;; Split symbol_refs at the later stage (after cprop), instead of generating
5533 ;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5534 ;; and lo_sum would be merged back into memory load at cprop. However,
5535 ;; if the default is to prefer movt/movw rather than a load from the constant
5536 ;; pool, the performance is better.
5537 (define_split
5538 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5539 (match_operand:SI 1 "general_operand" ""))]
5540 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5541 && !target_word_relocations
5542 && !arm_tls_referenced_p (operands[1])"
5543 [(clobber (const_int 0))]
5544 {
5545 arm_emit_movpair (operands[0], operands[1]);
5546 DONE;
5547 })
5548
5549 ;; When generating pic, we need to load the symbol offset into a register.
5550 ;; So that the optimizer does not confuse this with a normal symbol load
5551 ;; we use an unspec. The offset will be loaded from a constant pool entry,
5552 ;; since that is the only type of relocation we can use.
5553
5554 ;; Wrap calculation of the whole PIC address in a single pattern for the
5555 ;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5556 ;; a PIC address involves two loads from memory, so we want to CSE it
5557 ;; as often as possible.
5558 ;; This pattern will be split into one of the pic_load_addr_* patterns
5559 ;; and a move after GCSE optimizations.
5560 ;;
5561 ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5562 (define_expand "calculate_pic_address"
5563 [(set (match_operand:SI 0 "register_operand")
5564 (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
5565 (unspec:SI [(match_operand:SI 2 "" "")]
5566 UNSPEC_PIC_SYM))))]
5567 "flag_pic"
5568 )
5569
5570 ;; Split calculate_pic_address into pic_load_addr_* and a move.
5571 (define_split
5572 [(set (match_operand:SI 0 "register_operand" "")
5573 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5574 (unspec:SI [(match_operand:SI 2 "" "")]
5575 UNSPEC_PIC_SYM))))]
5576 "flag_pic"
5577 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5578 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5579 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5580 )
5581
5582 ;; operand1 is the memory address to go into
5583 ;; pic_load_addr_32bit.
5584 ;; operand2 is the PIC label to be emitted
5585 ;; from pic_add_dot_plus_eight.
5586 ;; We do this to allow hoisting of the entire insn.
5587 (define_insn_and_split "pic_load_addr_unified"
5588 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5589 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5590 (match_operand:SI 2 "" "")]
5591 UNSPEC_PIC_UNIFIED))]
5592 "flag_pic"
5593 "#"
5594 "&& reload_completed"
5595 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5596 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5597 (match_dup 2)] UNSPEC_PIC_BASE))]
5598 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5599 [(set_attr "type" "load_4,load_4,load_4")
5600 (set_attr "pool_range" "4096,4094,1022")
5601 (set_attr "neg_pool_range" "4084,0,0")
5602 (set_attr "arch" "a,t2,t1")
5603 (set_attr "length" "8,6,4")]
5604 )
5605
5606 ;; The rather odd constraints on the following are to force reload to leave
5607 ;; the insn alone, and to force the minipool generation pass to then move
5608 ;; the GOT symbol to memory.
5609
5610 (define_insn "pic_load_addr_32bit"
5611 [(set (match_operand:SI 0 "s_register_operand" "=r")
5612 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5613 "TARGET_32BIT && flag_pic"
5614 "ldr%?\\t%0, %1"
5615 [(set_attr "type" "load_4")
5616 (set (attr "pool_range")
5617 (if_then_else (eq_attr "is_thumb" "no")
5618 (const_int 4096)
5619 (const_int 4094)))
5620 (set (attr "neg_pool_range")
5621 (if_then_else (eq_attr "is_thumb" "no")
5622 (const_int 4084)
5623 (const_int 0)))]
5624 )
5625
5626 (define_insn "pic_load_addr_thumb1"
5627 [(set (match_operand:SI 0 "s_register_operand" "=l")
5628 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5629 "TARGET_THUMB1 && flag_pic"
5630 "ldr\\t%0, %1"
5631 [(set_attr "type" "load_4")
5632 (set (attr "pool_range") (const_int 1018))]
5633 )
5634
5635 (define_insn "pic_add_dot_plus_four"
5636 [(set (match_operand:SI 0 "register_operand" "=r")
5637 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5638 (const_int 4)
5639 (match_operand 2 "" "")]
5640 UNSPEC_PIC_BASE))]
5641 "TARGET_THUMB"
5642 "*
5643 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5644 INTVAL (operands[2]));
5645 return \"add\\t%0, %|pc\";
5646 "
5647 [(set_attr "length" "2")
5648 (set_attr "type" "alu_sreg")]
5649 )
5650
5651 (define_insn "pic_add_dot_plus_eight"
5652 [(set (match_operand:SI 0 "register_operand" "=r")
5653 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5654 (const_int 8)
5655 (match_operand 2 "" "")]
5656 UNSPEC_PIC_BASE))]
5657 "TARGET_ARM"
5658 "*
5659 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5660 INTVAL (operands[2]));
5661 return \"add%?\\t%0, %|pc, %1\";
5662 "
5663 [(set_attr "predicable" "yes")
5664 (set_attr "type" "alu_sreg")]
5665 )
5666
5667 (define_insn "tls_load_dot_plus_eight"
5668 [(set (match_operand:SI 0 "register_operand" "=r")
5669 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5670 (const_int 8)
5671 (match_operand 2 "" "")]
5672 UNSPEC_PIC_BASE)))]
5673 "TARGET_ARM"
5674 "*
5675 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5676 INTVAL (operands[2]));
5677 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5678 "
5679 [(set_attr "predicable" "yes")
5680 (set_attr "type" "load_4")]
5681 )
5682
5683 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5684 ;; followed by a load. These sequences can be crunched down to
5685 ;; tls_load_dot_plus_eight by a peephole.
5686
5687 (define_peephole2
5688 [(set (match_operand:SI 0 "register_operand" "")
5689 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5690 (const_int 8)
5691 (match_operand 1 "" "")]
5692 UNSPEC_PIC_BASE))
5693 (set (match_operand:SI 2 "arm_general_register_operand" "")
5694 (mem:SI (match_dup 0)))]
5695 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5696 [(set (match_dup 2)
5697 (mem:SI (unspec:SI [(match_dup 3)
5698 (const_int 8)
5699 (match_dup 1)]
5700 UNSPEC_PIC_BASE)))]
5701 ""
5702 )
5703
5704 (define_insn "pic_offset_arm"
5705 [(set (match_operand:SI 0 "register_operand" "=r")
5706 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5707 (unspec:SI [(match_operand:SI 2 "" "X")]
5708 UNSPEC_PIC_OFFSET))))]
5709 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5710 "ldr%?\\t%0, [%1,%2]"
5711 [(set_attr "type" "load_4")]
5712 )
5713
5714 (define_expand "builtin_setjmp_receiver"
5715 [(label_ref (match_operand 0 "" ""))]
5716 "flag_pic"
5717 "
5718 {
5719 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5720 register. */
5721 if (arm_pic_register != INVALID_REGNUM)
5722 arm_load_pic_register (1UL << 3, NULL_RTX);
5723 DONE;
5724 }")
5725
5726 ;; If copying one reg to another we can set the condition codes according to
5727 ;; its value. Such a move is common after a return from subroutine and the
5728 ;; result is being tested against zero.
5729
5730 (define_insn "*movsi_compare0"
5731 [(set (reg:CC CC_REGNUM)
5732 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5733 (const_int 0)))
5734 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5735 (match_dup 1))]
5736 "TARGET_32BIT"
5737 "@
5738 cmp%?\\t%0, #0
5739 subs%?\\t%0, %1, #0"
5740 [(set_attr "conds" "set")
5741 (set_attr "type" "alus_imm,alus_imm")]
5742 )
5743
5744 ;; Subroutine to store a half word from a register into memory.
5745 ;; Operand 0 is the source register (HImode)
5746 ;; Operand 1 is the destination address in a register (SImode)
5747
5748 ;; In both this routine and the next, we must be careful not to spill
5749 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5750 ;; can generate unrecognizable rtl.
5751
5752 (define_expand "storehi"
5753 [;; store the low byte
5754 (set (match_operand 1 "" "") (match_dup 3))
5755 ;; extract the high byte
5756 (set (match_dup 2)
5757 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5758 ;; store the high byte
5759 (set (match_dup 4) (match_dup 5))]
5760 "TARGET_ARM"
5761 "
5762 {
5763 rtx op1 = operands[1];
5764 rtx addr = XEXP (op1, 0);
5765 enum rtx_code code = GET_CODE (addr);
5766
5767 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5768 || code == MINUS)
5769 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5770
5771 operands[4] = adjust_address (op1, QImode, 1);
5772 operands[1] = adjust_address (operands[1], QImode, 0);
5773 operands[3] = gen_lowpart (QImode, operands[0]);
5774 operands[0] = gen_lowpart (SImode, operands[0]);
5775 operands[2] = gen_reg_rtx (SImode);
5776 operands[5] = gen_lowpart (QImode, operands[2]);
5777 }"
5778 )
5779
5780 (define_expand "storehi_bigend"
5781 [(set (match_dup 4) (match_dup 3))
5782 (set (match_dup 2)
5783 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5784 (set (match_operand 1 "" "") (match_dup 5))]
5785 "TARGET_ARM"
5786 "
5787 {
5788 rtx op1 = operands[1];
5789 rtx addr = XEXP (op1, 0);
5790 enum rtx_code code = GET_CODE (addr);
5791
5792 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5793 || code == MINUS)
5794 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5795
5796 operands[4] = adjust_address (op1, QImode, 1);
5797 operands[1] = adjust_address (operands[1], QImode, 0);
5798 operands[3] = gen_lowpart (QImode, operands[0]);
5799 operands[0] = gen_lowpart (SImode, operands[0]);
5800 operands[2] = gen_reg_rtx (SImode);
5801 operands[5] = gen_lowpart (QImode, operands[2]);
5802 }"
5803 )
5804
5805 ;; Subroutine to store a half word integer constant into memory.
5806 (define_expand "storeinthi"
5807 [(set (match_operand 0 "" "")
5808 (match_operand 1 "" ""))
5809 (set (match_dup 3) (match_dup 2))]
5810 "TARGET_ARM"
5811 "
5812 {
5813 HOST_WIDE_INT value = INTVAL (operands[1]);
5814 rtx addr = XEXP (operands[0], 0);
5815 rtx op0 = operands[0];
5816 enum rtx_code code = GET_CODE (addr);
5817
5818 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5819 || code == MINUS)
5820 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5821
5822 operands[1] = gen_reg_rtx (SImode);
5823 if (BYTES_BIG_ENDIAN)
5824 {
5825 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5826 if ((value & 255) == ((value >> 8) & 255))
5827 operands[2] = operands[1];
5828 else
5829 {
5830 operands[2] = gen_reg_rtx (SImode);
5831 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5832 }
5833 }
5834 else
5835 {
5836 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5837 if ((value & 255) == ((value >> 8) & 255))
5838 operands[2] = operands[1];
5839 else
5840 {
5841 operands[2] = gen_reg_rtx (SImode);
5842 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5843 }
5844 }
5845
5846 operands[3] = adjust_address (op0, QImode, 1);
5847 operands[0] = adjust_address (operands[0], QImode, 0);
5848 operands[2] = gen_lowpart (QImode, operands[2]);
5849 operands[1] = gen_lowpart (QImode, operands[1]);
5850 }"
5851 )
5852
5853 (define_expand "storehi_single_op"
5854 [(set (match_operand:HI 0 "memory_operand")
5855 (match_operand:HI 1 "general_operand"))]
5856 "TARGET_32BIT && arm_arch4"
5857 "
5858 if (!s_register_operand (operands[1], HImode))
5859 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5860 "
5861 )
5862
5863 (define_expand "movhi"
5864 [(set (match_operand:HI 0 "general_operand")
5865 (match_operand:HI 1 "general_operand"))]
5866 "TARGET_EITHER"
5867 "
5868 gcc_checking_assert (aligned_operand (operands[0], HImode));
5869 gcc_checking_assert (aligned_operand (operands[1], HImode));
5870 if (TARGET_ARM)
5871 {
5872 if (can_create_pseudo_p ())
5873 {
5874 if (MEM_P (operands[0]))
5875 {
5876 if (arm_arch4)
5877 {
5878 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5879 DONE;
5880 }
5881 if (CONST_INT_P (operands[1]))
5882 emit_insn (gen_storeinthi (operands[0], operands[1]));
5883 else
5884 {
5885 if (MEM_P (operands[1]))
5886 operands[1] = force_reg (HImode, operands[1]);
5887 if (BYTES_BIG_ENDIAN)
5888 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5889 else
5890 emit_insn (gen_storehi (operands[1], operands[0]));
5891 }
5892 DONE;
5893 }
5894 /* Sign extend a constant, and keep it in an SImode reg. */
5895 else if (CONST_INT_P (operands[1]))
5896 {
5897 rtx reg = gen_reg_rtx (SImode);
5898 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5899
5900 /* If the constant is already valid, leave it alone. */
5901 if (!const_ok_for_arm (val))
5902 {
5903 /* If setting all the top bits will make the constant
5904 loadable in a single instruction, then set them.
5905 Otherwise, sign extend the number. */
5906
5907 if (const_ok_for_arm (~(val | ~0xffff)))
5908 val |= ~0xffff;
5909 else if (val & 0x8000)
5910 val |= ~0xffff;
5911 }
5912
5913 emit_insn (gen_movsi (reg, GEN_INT (val)));
5914 operands[1] = gen_lowpart (HImode, reg);
5915 }
5916 else if (arm_arch4 && optimize && can_create_pseudo_p ()
5917 && MEM_P (operands[1]))
5918 {
5919 rtx reg = gen_reg_rtx (SImode);
5920
5921 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5922 operands[1] = gen_lowpart (HImode, reg);
5923 }
5924 else if (!arm_arch4)
5925 {
5926 if (MEM_P (operands[1]))
5927 {
5928 rtx base;
5929 rtx offset = const0_rtx;
5930 rtx reg = gen_reg_rtx (SImode);
5931
5932 if ((REG_P (base = XEXP (operands[1], 0))
5933 || (GET_CODE (base) == PLUS
5934 && (CONST_INT_P (offset = XEXP (base, 1)))
5935 && ((INTVAL(offset) & 1) != 1)
5936 && REG_P (base = XEXP (base, 0))))
5937 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5938 {
5939 rtx new_rtx;
5940
5941 new_rtx = widen_memory_access (operands[1], SImode,
5942 ((INTVAL (offset) & ~3)
5943 - INTVAL (offset)));
5944 emit_insn (gen_movsi (reg, new_rtx));
5945 if (((INTVAL (offset) & 2) != 0)
5946 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5947 {
5948 rtx reg2 = gen_reg_rtx (SImode);
5949
5950 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5951 reg = reg2;
5952 }
5953 }
5954 else
5955 emit_insn (gen_movhi_bytes (reg, operands[1]));
5956
5957 operands[1] = gen_lowpart (HImode, reg);
5958 }
5959 }
5960 }
5961 /* Handle loading a large integer during reload. */
5962 else if (CONST_INT_P (operands[1])
5963 && !const_ok_for_arm (INTVAL (operands[1]))
5964 && !const_ok_for_arm (~INTVAL (operands[1])))
5965 {
5966 /* Writing a constant to memory needs a scratch, which should
5967 be handled with SECONDARY_RELOADs. */
5968 gcc_assert (REG_P (operands[0]));
5969
5970 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5971 emit_insn (gen_movsi (operands[0], operands[1]));
5972 DONE;
5973 }
5974 }
5975 else if (TARGET_THUMB2)
5976 {
5977 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
5978 if (can_create_pseudo_p ())
5979 {
5980 if (!REG_P (operands[0]))
5981 operands[1] = force_reg (HImode, operands[1]);
5982 /* Zero extend a constant, and keep it in an SImode reg. */
5983 else if (CONST_INT_P (operands[1]))
5984 {
5985 rtx reg = gen_reg_rtx (SImode);
5986 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5987
5988 emit_insn (gen_movsi (reg, GEN_INT (val)));
5989 operands[1] = gen_lowpart (HImode, reg);
5990 }
5991 }
5992 }
5993 else /* TARGET_THUMB1 */
5994 {
5995 if (can_create_pseudo_p ())
5996 {
5997 if (CONST_INT_P (operands[1]))
5998 {
5999 rtx reg = gen_reg_rtx (SImode);
6000
6001 emit_insn (gen_movsi (reg, operands[1]));
6002 operands[1] = gen_lowpart (HImode, reg);
6003 }
6004
6005 /* ??? We shouldn't really get invalid addresses here, but this can
6006 happen if we are passed a SP (never OK for HImode/QImode) or
6007 virtual register (also rejected as illegitimate for HImode/QImode)
6008 relative address. */
6009 /* ??? This should perhaps be fixed elsewhere, for instance, in
6010 fixup_stack_1, by checking for other kinds of invalid addresses,
6011 e.g. a bare reference to a virtual register. This may confuse the
6012 alpha though, which must handle this case differently. */
6013 if (MEM_P (operands[0])
6014 && !memory_address_p (GET_MODE (operands[0]),
6015 XEXP (operands[0], 0)))
6016 operands[0]
6017 = replace_equiv_address (operands[0],
6018 copy_to_reg (XEXP (operands[0], 0)));
6019
6020 if (MEM_P (operands[1])
6021 && !memory_address_p (GET_MODE (operands[1]),
6022 XEXP (operands[1], 0)))
6023 operands[1]
6024 = replace_equiv_address (operands[1],
6025 copy_to_reg (XEXP (operands[1], 0)));
6026
6027 if (MEM_P (operands[1]) && optimize > 0)
6028 {
6029 rtx reg = gen_reg_rtx (SImode);
6030
6031 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6032 operands[1] = gen_lowpart (HImode, reg);
6033 }
6034
6035 if (MEM_P (operands[0]))
6036 operands[1] = force_reg (HImode, operands[1]);
6037 }
6038 else if (CONST_INT_P (operands[1])
6039 && !satisfies_constraint_I (operands[1]))
6040 {
6041 /* Handle loading a large integer during reload. */
6042
6043 /* Writing a constant to memory needs a scratch, which should
6044 be handled with SECONDARY_RELOADs. */
6045 gcc_assert (REG_P (operands[0]));
6046
6047 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6048 emit_insn (gen_movsi (operands[0], operands[1]));
6049 DONE;
6050 }
6051 }
6052 "
6053 )
6054
6055 (define_expand "movhi_bytes"
6056 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6057 (set (match_dup 3)
6058 (zero_extend:SI (match_dup 6)))
6059 (set (match_operand:SI 0 "" "")
6060 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6061 "TARGET_ARM"
6062 "
6063 {
6064 rtx mem1, mem2;
6065 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6066
6067 mem1 = change_address (operands[1], QImode, addr);
6068 mem2 = change_address (operands[1], QImode,
6069 plus_constant (Pmode, addr, 1));
6070 operands[0] = gen_lowpart (SImode, operands[0]);
6071 operands[1] = mem1;
6072 operands[2] = gen_reg_rtx (SImode);
6073 operands[3] = gen_reg_rtx (SImode);
6074 operands[6] = mem2;
6075
6076 if (BYTES_BIG_ENDIAN)
6077 {
6078 operands[4] = operands[2];
6079 operands[5] = operands[3];
6080 }
6081 else
6082 {
6083 operands[4] = operands[3];
6084 operands[5] = operands[2];
6085 }
6086 }"
6087 )
6088
6089 (define_expand "movhi_bigend"
6090 [(set (match_dup 2)
6091 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
6092 (const_int 16)))
6093 (set (match_dup 3)
6094 (ashiftrt:SI (match_dup 2) (const_int 16)))
6095 (set (match_operand:HI 0 "s_register_operand")
6096 (match_dup 4))]
6097 "TARGET_ARM"
6098 "
6099 operands[2] = gen_reg_rtx (SImode);
6100 operands[3] = gen_reg_rtx (SImode);
6101 operands[4] = gen_lowpart (HImode, operands[3]);
6102 "
6103 )
6104
6105 ;; Pattern to recognize insn generated default case above
6106 (define_insn "*movhi_insn_arch4"
6107 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6108 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
6109 "TARGET_ARM
6110 && arm_arch4 && !TARGET_HARD_FLOAT
6111 && (register_operand (operands[0], HImode)
6112 || register_operand (operands[1], HImode))"
6113 "@
6114 mov%?\\t%0, %1\\t%@ movhi
6115 mvn%?\\t%0, #%B1\\t%@ movhi
6116 movw%?\\t%0, %L1\\t%@ movhi
6117 strh%?\\t%1, %0\\t%@ movhi
6118 ldrh%?\\t%0, %1\\t%@ movhi"
6119 [(set_attr "predicable" "yes")
6120 (set_attr "pool_range" "*,*,*,*,256")
6121 (set_attr "neg_pool_range" "*,*,*,*,244")
6122 (set_attr "arch" "*,*,v6t2,*,*")
6123 (set_attr_alternative "type"
6124 [(if_then_else (match_operand 1 "const_int_operand" "")
6125 (const_string "mov_imm" )
6126 (const_string "mov_reg"))
6127 (const_string "mvn_imm")
6128 (const_string "mov_imm")
6129 (const_string "store_4")
6130 (const_string "load_4")])]
6131 )
6132
6133 (define_insn "*movhi_bytes"
6134 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
6135 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
6136 "TARGET_ARM && !TARGET_HARD_FLOAT"
6137 "@
6138 mov%?\\t%0, %1\\t%@ movhi
6139 mov%?\\t%0, %1\\t%@ movhi
6140 mvn%?\\t%0, #%B1\\t%@ movhi"
6141 [(set_attr "predicable" "yes")
6142 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
6143 )
6144
6145 ;; We use a DImode scratch because we may occasionally need an additional
6146 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
6147 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
6148 ;; The reload_in<m> and reload_out<m> patterns require special constraints
6149 ;; to be correctly handled in default_secondary_reload function.
6150 (define_expand "reload_outhi"
6151 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6152 (match_operand:HI 1 "s_register_operand" "r")
6153 (match_operand:DI 2 "s_register_operand" "=&l")])]
6154 "TARGET_EITHER"
6155 "if (TARGET_ARM)
6156 arm_reload_out_hi (operands);
6157 else
6158 thumb_reload_out_hi (operands);
6159 DONE;
6160 "
6161 )
6162
6163 (define_expand "reload_inhi"
6164 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6165 (match_operand:HI 1 "arm_reload_memory_operand" "o")
6166 (match_operand:DI 2 "s_register_operand" "=&r")])]
6167 "TARGET_EITHER"
6168 "
6169 if (TARGET_ARM)
6170 arm_reload_in_hi (operands);
6171 else
6172 thumb_reload_out_hi (operands);
6173 DONE;
6174 ")
6175
6176 (define_expand "movqi"
6177 [(set (match_operand:QI 0 "general_operand")
6178 (match_operand:QI 1 "general_operand"))]
6179 "TARGET_EITHER"
6180 "
6181 /* Everything except mem = const or mem = mem can be done easily */
6182
6183 if (can_create_pseudo_p ())
6184 {
6185 if (CONST_INT_P (operands[1]))
6186 {
6187 rtx reg = gen_reg_rtx (SImode);
6188
6189 /* For thumb we want an unsigned immediate, then we are more likely
6190 to be able to use a movs insn. */
6191 if (TARGET_THUMB)
6192 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6193
6194 emit_insn (gen_movsi (reg, operands[1]));
6195 operands[1] = gen_lowpart (QImode, reg);
6196 }
6197
6198 if (TARGET_THUMB)
6199 {
6200 /* ??? We shouldn't really get invalid addresses here, but this can
6201 happen if we are passed a SP (never OK for HImode/QImode) or
6202 virtual register (also rejected as illegitimate for HImode/QImode)
6203 relative address. */
6204 /* ??? This should perhaps be fixed elsewhere, for instance, in
6205 fixup_stack_1, by checking for other kinds of invalid addresses,
6206 e.g. a bare reference to a virtual register. This may confuse the
6207 alpha though, which must handle this case differently. */
6208 if (MEM_P (operands[0])
6209 && !memory_address_p (GET_MODE (operands[0]),
6210 XEXP (operands[0], 0)))
6211 operands[0]
6212 = replace_equiv_address (operands[0],
6213 copy_to_reg (XEXP (operands[0], 0)));
6214 if (MEM_P (operands[1])
6215 && !memory_address_p (GET_MODE (operands[1]),
6216 XEXP (operands[1], 0)))
6217 operands[1]
6218 = replace_equiv_address (operands[1],
6219 copy_to_reg (XEXP (operands[1], 0)));
6220 }
6221
6222 if (MEM_P (operands[1]) && optimize > 0)
6223 {
6224 rtx reg = gen_reg_rtx (SImode);
6225
6226 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6227 operands[1] = gen_lowpart (QImode, reg);
6228 }
6229
6230 if (MEM_P (operands[0]))
6231 operands[1] = force_reg (QImode, operands[1]);
6232 }
6233 else if (TARGET_THUMB
6234 && CONST_INT_P (operands[1])
6235 && !satisfies_constraint_I (operands[1]))
6236 {
6237 /* Handle loading a large integer during reload. */
6238
6239 /* Writing a constant to memory needs a scratch, which should
6240 be handled with SECONDARY_RELOADs. */
6241 gcc_assert (REG_P (operands[0]));
6242
6243 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6244 emit_insn (gen_movsi (operands[0], operands[1]));
6245 DONE;
6246 }
6247 "
6248 )
6249
6250 (define_insn "*arm_movqi_insn"
6251 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
6252 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
6253 "TARGET_32BIT
6254 && ( register_operand (operands[0], QImode)
6255 || register_operand (operands[1], QImode))"
6256 "@
6257 mov%?\\t%0, %1
6258 mov%?\\t%0, %1
6259 mov%?\\t%0, %1
6260 mov%?\\t%0, %1
6261 mvn%?\\t%0, #%B1
6262 ldrb%?\\t%0, %1
6263 strb%?\\t%1, %0
6264 ldrb%?\\t%0, %1
6265 strb%?\\t%1, %0"
6266 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
6267 (set_attr "predicable" "yes")
6268 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
6269 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6270 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
6271 )
6272
6273 ;; HFmode moves
6274 (define_expand "movhf"
6275 [(set (match_operand:HF 0 "general_operand")
6276 (match_operand:HF 1 "general_operand"))]
6277 "TARGET_EITHER"
6278 "
6279 gcc_checking_assert (aligned_operand (operands[0], HFmode));
6280 gcc_checking_assert (aligned_operand (operands[1], HFmode));
6281 if (TARGET_32BIT)
6282 {
6283 if (MEM_P (operands[0]))
6284 operands[1] = force_reg (HFmode, operands[1]);
6285 }
6286 else /* TARGET_THUMB1 */
6287 {
6288 if (can_create_pseudo_p ())
6289 {
6290 if (!REG_P (operands[0]))
6291 operands[1] = force_reg (HFmode, operands[1]);
6292 }
6293 }
6294 "
6295 )
6296
6297 (define_insn "*arm32_movhf"
6298 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6299 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6300 "TARGET_32BIT && !TARGET_HARD_FLOAT
6301 && ( s_register_operand (operands[0], HFmode)
6302 || s_register_operand (operands[1], HFmode))"
6303 "*
6304 switch (which_alternative)
6305 {
6306 case 0: /* ARM register from memory */
6307 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
6308 case 1: /* memory from ARM register */
6309 return \"strh%?\\t%1, %0\\t%@ __fp16\";
6310 case 2: /* ARM register from ARM register */
6311 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6312 case 3: /* ARM register from constant */
6313 {
6314 long bits;
6315 rtx ops[4];
6316
6317 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6318 HFmode);
6319 ops[0] = operands[0];
6320 ops[1] = GEN_INT (bits);
6321 ops[2] = GEN_INT (bits & 0xff00);
6322 ops[3] = GEN_INT (bits & 0x00ff);
6323
6324 if (arm_arch_thumb2)
6325 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6326 else
6327 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6328 return \"\";
6329 }
6330 default:
6331 gcc_unreachable ();
6332 }
6333 "
6334 [(set_attr "conds" "unconditional")
6335 (set_attr "type" "load_4,store_4,mov_reg,multiple")
6336 (set_attr "length" "4,4,4,8")
6337 (set_attr "predicable" "yes")]
6338 )
6339
6340 (define_expand "movsf"
6341 [(set (match_operand:SF 0 "general_operand")
6342 (match_operand:SF 1 "general_operand"))]
6343 "TARGET_EITHER"
6344 "
6345 gcc_checking_assert (aligned_operand (operands[0], SFmode));
6346 gcc_checking_assert (aligned_operand (operands[1], SFmode));
6347 if (TARGET_32BIT)
6348 {
6349 if (MEM_P (operands[0]))
6350 operands[1] = force_reg (SFmode, operands[1]);
6351 }
6352 else /* TARGET_THUMB1 */
6353 {
6354 if (can_create_pseudo_p ())
6355 {
6356 if (!REG_P (operands[0]))
6357 operands[1] = force_reg (SFmode, operands[1]);
6358 }
6359 }
6360
6361 /* Cannot load it directly, generate a load with clobber so that it can be
6362 loaded via GPR with MOV / MOVT. */
6363 if (arm_disable_literal_pool
6364 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6365 && CONST_DOUBLE_P (operands[1])
6366 && TARGET_HARD_FLOAT
6367 && !vfp3_const_double_rtx (operands[1]))
6368 {
6369 rtx clobreg = gen_reg_rtx (SFmode);
6370 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6371 clobreg));
6372 DONE;
6373 }
6374 "
6375 )
6376
6377 ;; Transform a floating-point move of a constant into a core register into
6378 ;; an SImode operation.
6379 (define_split
6380 [(set (match_operand:SF 0 "arm_general_register_operand" "")
6381 (match_operand:SF 1 "immediate_operand" ""))]
6382 "TARGET_EITHER
6383 && reload_completed
6384 && CONST_DOUBLE_P (operands[1])"
6385 [(set (match_dup 2) (match_dup 3))]
6386 "
6387 operands[2] = gen_lowpart (SImode, operands[0]);
6388 operands[3] = gen_lowpart (SImode, operands[1]);
6389 if (operands[2] == 0 || operands[3] == 0)
6390 FAIL;
6391 "
6392 )
6393
6394 (define_insn "*arm_movsf_soft_insn"
6395 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6396 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6397 "TARGET_32BIT
6398 && TARGET_SOFT_FLOAT
6399 && (!MEM_P (operands[0])
6400 || register_operand (operands[1], SFmode))"
6401 {
6402 switch (which_alternative)
6403 {
6404 case 0: return \"mov%?\\t%0, %1\";
6405 case 1:
6406 /* Cannot load it directly, split to load it via MOV / MOVT. */
6407 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6408 return \"#\";
6409 return \"ldr%?\\t%0, %1\\t%@ float\";
6410 case 2: return \"str%?\\t%1, %0\\t%@ float\";
6411 default: gcc_unreachable ();
6412 }
6413 }
6414 [(set_attr "predicable" "yes")
6415 (set_attr "type" "mov_reg,load_4,store_4")
6416 (set_attr "arm_pool_range" "*,4096,*")
6417 (set_attr "thumb2_pool_range" "*,4094,*")
6418 (set_attr "arm_neg_pool_range" "*,4084,*")
6419 (set_attr "thumb2_neg_pool_range" "*,0,*")]
6420 )
6421
6422 ;; Splitter for the above.
6423 (define_split
6424 [(set (match_operand:SF 0 "s_register_operand")
6425 (match_operand:SF 1 "const_double_operand"))]
6426 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6427 [(const_int 0)]
6428 {
6429 long buf;
6430 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
6431 rtx cst = gen_int_mode (buf, SImode);
6432 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
6433 DONE;
6434 }
6435 )
6436
6437 (define_expand "movdf"
6438 [(set (match_operand:DF 0 "general_operand")
6439 (match_operand:DF 1 "general_operand"))]
6440 "TARGET_EITHER"
6441 "
6442 gcc_checking_assert (aligned_operand (operands[0], DFmode));
6443 gcc_checking_assert (aligned_operand (operands[1], DFmode));
6444 if (TARGET_32BIT)
6445 {
6446 if (MEM_P (operands[0]))
6447 operands[1] = force_reg (DFmode, operands[1]);
6448 }
6449 else /* TARGET_THUMB */
6450 {
6451 if (can_create_pseudo_p ())
6452 {
6453 if (!REG_P (operands[0]))
6454 operands[1] = force_reg (DFmode, operands[1]);
6455 }
6456 }
6457
6458 /* Cannot load it directly, generate a load with clobber so that it can be
6459 loaded via GPR with MOV / MOVT. */
6460 if (arm_disable_literal_pool
6461 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6462 && CONSTANT_P (operands[1])
6463 && TARGET_HARD_FLOAT
6464 && !arm_const_double_rtx (operands[1])
6465 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
6466 {
6467 rtx clobreg = gen_reg_rtx (DFmode);
6468 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
6469 clobreg));
6470 DONE;
6471 }
6472 "
6473 )
6474
6475 ;; Reloading a df mode value stored in integer regs to memory can require a
6476 ;; scratch reg.
6477 ;; Another reload_out<m> pattern that requires special constraints.
6478 (define_expand "reload_outdf"
6479 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6480 (match_operand:DF 1 "s_register_operand" "r")
6481 (match_operand:SI 2 "s_register_operand" "=&r")]
6482 "TARGET_THUMB2"
6483 "
6484 {
6485 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6486
6487 if (code == REG)
6488 operands[2] = XEXP (operands[0], 0);
6489 else if (code == POST_INC || code == PRE_DEC)
6490 {
6491 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6492 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6493 emit_insn (gen_movdi (operands[0], operands[1]));
6494 DONE;
6495 }
6496 else if (code == PRE_INC)
6497 {
6498 rtx reg = XEXP (XEXP (operands[0], 0), 0);
6499
6500 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6501 operands[2] = reg;
6502 }
6503 else if (code == POST_DEC)
6504 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6505 else
6506 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6507 XEXP (XEXP (operands[0], 0), 1)));
6508
6509 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
6510 operands[1]));
6511
6512 if (code == POST_DEC)
6513 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6514
6515 DONE;
6516 }"
6517 )
6518
6519 (define_insn "*movdf_soft_insn"
6520 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6521 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6522 "TARGET_32BIT && TARGET_SOFT_FLOAT
6523 && ( register_operand (operands[0], DFmode)
6524 || register_operand (operands[1], DFmode))"
6525 "*
6526 switch (which_alternative)
6527 {
6528 case 0:
6529 case 1:
6530 case 2:
6531 return \"#\";
6532 case 3:
6533 /* Cannot load it directly, split to load it via MOV / MOVT. */
6534 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6535 return \"#\";
6536 /* Fall through. */
6537 default:
6538 return output_move_double (operands, true, NULL);
6539 }
6540 "
6541 [(set_attr "length" "8,12,16,8,8")
6542 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
6543 (set_attr "arm_pool_range" "*,*,*,1020,*")
6544 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
6545 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
6546 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
6547 )
6548
6549 ;; Splitter for the above.
6550 (define_split
6551 [(set (match_operand:DF 0 "s_register_operand")
6552 (match_operand:DF 1 "const_double_operand"))]
6553 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6554 [(const_int 0)]
6555 {
6556 long buf[2];
6557 int order = BYTES_BIG_ENDIAN ? 1 : 0;
6558 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
6559 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
6560 ival |= (zext_hwi (buf[1 - order], 32) << 32);
6561 rtx cst = gen_int_mode (ival, DImode);
6562 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
6563 DONE;
6564 }
6565 )
6566 \f
6567
6568 ;; load- and store-multiple insns
6569 ;; The arm can load/store any set of registers, provided that they are in
6570 ;; ascending order, but these expanders assume a contiguous set.
6571
6572 (define_expand "load_multiple"
6573 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6574 (match_operand:SI 1 "" ""))
6575 (use (match_operand:SI 2 "" ""))])]
6576 "TARGET_32BIT"
6577 {
6578 HOST_WIDE_INT offset = 0;
6579
6580 /* Support only fixed point registers. */
6581 if (!CONST_INT_P (operands[2])
6582 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
6583 || INTVAL (operands[2]) < 2
6584 || !MEM_P (operands[1])
6585 || !REG_P (operands[0])
6586 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6587 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6588 FAIL;
6589
6590 operands[3]
6591 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6592 INTVAL (operands[2]),
6593 force_reg (SImode, XEXP (operands[1], 0)),
6594 FALSE, operands[1], &offset);
6595 })
6596
6597 (define_expand "store_multiple"
6598 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6599 (match_operand:SI 1 "" ""))
6600 (use (match_operand:SI 2 "" ""))])]
6601 "TARGET_32BIT"
6602 {
6603 HOST_WIDE_INT offset = 0;
6604
6605 /* Support only fixed point registers. */
6606 if (!CONST_INT_P (operands[2])
6607 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
6608 || INTVAL (operands[2]) < 2
6609 || !REG_P (operands[1])
6610 || !MEM_P (operands[0])
6611 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6612 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6613 FAIL;
6614
6615 operands[3]
6616 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6617 INTVAL (operands[2]),
6618 force_reg (SImode, XEXP (operands[0], 0)),
6619 FALSE, operands[0], &offset);
6620 })
6621
6622
6623 (define_expand "setmemsi"
6624 [(match_operand:BLK 0 "general_operand")
6625 (match_operand:SI 1 "const_int_operand")
6626 (match_operand:SI 2 "const_int_operand")
6627 (match_operand:SI 3 "const_int_operand")]
6628 "TARGET_32BIT"
6629 {
6630 if (arm_gen_setmem (operands))
6631 DONE;
6632
6633 FAIL;
6634 })
6635
6636
6637 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6638 ;; We could let this apply for blocks of less than this, but it clobbers so
6639 ;; many registers that there is then probably a better way.
6640
6641 (define_expand "cpymemqi"
6642 [(match_operand:BLK 0 "general_operand")
6643 (match_operand:BLK 1 "general_operand")
6644 (match_operand:SI 2 "const_int_operand")
6645 (match_operand:SI 3 "const_int_operand")]
6646 ""
6647 "
6648 if (TARGET_32BIT)
6649 {
6650 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6651 && !optimize_function_for_size_p (cfun))
6652 {
6653 if (gen_cpymem_ldrd_strd (operands))
6654 DONE;
6655 FAIL;
6656 }
6657
6658 if (arm_gen_cpymemqi (operands))
6659 DONE;
6660 FAIL;
6661 }
6662 else /* TARGET_THUMB1 */
6663 {
6664 if ( INTVAL (operands[3]) != 4
6665 || INTVAL (operands[2]) > 48)
6666 FAIL;
6667
6668 thumb_expand_cpymemqi (operands);
6669 DONE;
6670 }
6671 "
6672 )
6673 \f
6674
6675 ;; Compare & branch insns
6676 ;; The range calculations are based as follows:
6677 ;; For forward branches, the address calculation returns the address of
6678 ;; the next instruction. This is 2 beyond the branch instruction.
6679 ;; For backward branches, the address calculation returns the address of
6680 ;; the first instruction in this pattern (cmp). This is 2 before the branch
6681 ;; instruction for the shortest sequence, and 4 before the branch instruction
6682 ;; if we have to jump around an unconditional branch.
6683 ;; To the basic branch range the PC offset must be added (this is +4).
6684 ;; So for forward branches we have
6685 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6686 ;; And for backward branches we have
6687 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6688 ;;
6689 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6690 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
6691
6692 (define_expand "cbranchsi4"
6693 [(set (pc) (if_then_else
6694 (match_operator 0 "expandable_comparison_operator"
6695 [(match_operand:SI 1 "s_register_operand")
6696 (match_operand:SI 2 "nonmemory_operand")])
6697 (label_ref (match_operand 3 "" ""))
6698 (pc)))]
6699 "TARGET_EITHER"
6700 "
6701 if (!TARGET_THUMB1)
6702 {
6703 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6704 FAIL;
6705 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6706 operands[3]));
6707 DONE;
6708 }
6709 if (thumb1_cmpneg_operand (operands[2], SImode))
6710 {
6711 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6712 operands[3], operands[0]));
6713 DONE;
6714 }
6715 if (!thumb1_cmp_operand (operands[2], SImode))
6716 operands[2] = force_reg (SImode, operands[2]);
6717 ")
6718
6719 (define_expand "cbranchsf4"
6720 [(set (pc) (if_then_else
6721 (match_operator 0 "expandable_comparison_operator"
6722 [(match_operand:SF 1 "s_register_operand")
6723 (match_operand:SF 2 "vfp_compare_operand")])
6724 (label_ref (match_operand 3 "" ""))
6725 (pc)))]
6726 "TARGET_32BIT && TARGET_HARD_FLOAT"
6727 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6728 operands[3])); DONE;"
6729 )
6730
6731 (define_expand "cbranchdf4"
6732 [(set (pc) (if_then_else
6733 (match_operator 0 "expandable_comparison_operator"
6734 [(match_operand:DF 1 "s_register_operand")
6735 (match_operand:DF 2 "vfp_compare_operand")])
6736 (label_ref (match_operand 3 "" ""))
6737 (pc)))]
6738 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6739 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6740 operands[3])); DONE;"
6741 )
6742
6743 (define_expand "cbranchdi4"
6744 [(set (pc) (if_then_else
6745 (match_operator 0 "expandable_comparison_operator"
6746 [(match_operand:DI 1 "s_register_operand")
6747 (match_operand:DI 2 "cmpdi_operand")])
6748 (label_ref (match_operand 3 "" ""))
6749 (pc)))]
6750 "TARGET_32BIT"
6751 "{
6752 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6753 FAIL;
6754 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6755 operands[3]));
6756 DONE;
6757 }"
6758 )
6759
6760 ;; Comparison and test insns
6761
6762 (define_insn "*arm_cmpsi_insn"
6763 [(set (reg:CC CC_REGNUM)
6764 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6765 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
6766 "TARGET_32BIT"
6767 "@
6768 cmp%?\\t%0, %1
6769 cmp%?\\t%0, %1
6770 cmp%?\\t%0, %1
6771 cmp%?\\t%0, %1
6772 cmn%?\\t%0, #%n1"
6773 [(set_attr "conds" "set")
6774 (set_attr "arch" "t2,t2,any,any,any")
6775 (set_attr "length" "2,2,4,4,4")
6776 (set_attr "predicable" "yes")
6777 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
6778 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
6779 )
6780
6781 (define_insn "*cmpsi_shiftsi"
6782 [(set (reg:CC CC_REGNUM)
6783 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
6784 (match_operator:SI 3 "shift_operator"
6785 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6786 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
6787 "TARGET_32BIT"
6788 "cmp\\t%0, %1%S3"
6789 [(set_attr "conds" "set")
6790 (set_attr "shift" "1")
6791 (set_attr "arch" "32,a,a")
6792 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
6793
6794 (define_insn "*cmpsi_shiftsi_swp"
6795 [(set (reg:CC_SWP CC_REGNUM)
6796 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6797 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6798 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6799 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
6800 "TARGET_32BIT"
6801 "cmp%?\\t%0, %1%S3"
6802 [(set_attr "conds" "set")
6803 (set_attr "shift" "1")
6804 (set_attr "arch" "32,a,a")
6805 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
6806
6807 (define_insn "*arm_cmpsi_negshiftsi_si"
6808 [(set (reg:CC_Z CC_REGNUM)
6809 (compare:CC_Z
6810 (neg:SI (match_operator:SI 1 "shift_operator"
6811 [(match_operand:SI 2 "s_register_operand" "r")
6812 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6813 (match_operand:SI 0 "s_register_operand" "r")))]
6814 "TARGET_ARM"
6815 "cmn%?\\t%0, %2%S1"
6816 [(set_attr "conds" "set")
6817 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6818 (const_string "alus_shift_imm")
6819 (const_string "alus_shift_reg")))
6820 (set_attr "predicable" "yes")]
6821 )
6822
6823 ;; DImode comparisons. The generic code generates branches that
6824 ;; if-conversion cannot reduce to a conditional compare, so we do
6825 ;; that directly.
6826
6827 (define_insn_and_split "*arm_cmpdi_insn"
6828 [(set (reg:CC_NCV CC_REGNUM)
6829 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
6830 (match_operand:DI 1 "arm_di_operand" "rDi")))
6831 (clobber (match_scratch:SI 2 "=r"))]
6832 "TARGET_32BIT"
6833 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
6834 "&& reload_completed"
6835 [(set (reg:CC CC_REGNUM)
6836 (compare:CC (match_dup 0) (match_dup 1)))
6837 (parallel [(set (reg:CC CC_REGNUM)
6838 (compare:CC (match_dup 3) (match_dup 4)))
6839 (set (match_dup 2)
6840 (minus:SI (match_dup 5)
6841 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
6842 {
6843 operands[3] = gen_highpart (SImode, operands[0]);
6844 operands[0] = gen_lowpart (SImode, operands[0]);
6845 if (CONST_INT_P (operands[1]))
6846 {
6847 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);
6848 if (operands[4] == const0_rtx)
6849 operands[5] = operands[3];
6850 else
6851 operands[5] = gen_rtx_PLUS (SImode, operands[3],
6852 gen_int_mode (-UINTVAL (operands[4]),
6853 SImode));
6854 }
6855 else
6856 {
6857 operands[4] = gen_highpart (SImode, operands[1]);
6858 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
6859 }
6860 operands[1] = gen_lowpart (SImode, operands[1]);
6861 operands[2] = gen_lowpart (SImode, operands[2]);
6862 }
6863 [(set_attr "conds" "set")
6864 (set_attr "length" "8")
6865 (set_attr "type" "multiple")]
6866 )
6867
6868 (define_insn_and_split "*arm_cmpdi_unsigned"
6869 [(set (reg:CC_CZ CC_REGNUM)
6870 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
6871 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
6872
6873 "TARGET_32BIT"
6874 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
6875 "&& reload_completed"
6876 [(set (reg:CC CC_REGNUM)
6877 (compare:CC (match_dup 2) (match_dup 3)))
6878 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
6879 (set (reg:CC CC_REGNUM)
6880 (compare:CC (match_dup 0) (match_dup 1))))]
6881 {
6882 operands[2] = gen_highpart (SImode, operands[0]);
6883 operands[0] = gen_lowpart (SImode, operands[0]);
6884 if (CONST_INT_P (operands[1]))
6885 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6886 else
6887 operands[3] = gen_highpart (SImode, operands[1]);
6888 operands[1] = gen_lowpart (SImode, operands[1]);
6889 }
6890 [(set_attr "conds" "set")
6891 (set_attr "enabled_for_short_it" "yes,yes,no,*")
6892 (set_attr "arch" "t2,t2,t2,a")
6893 (set_attr "length" "6,6,10,8")
6894 (set_attr "type" "multiple")]
6895 )
6896
6897 (define_insn "*arm_cmpdi_zero"
6898 [(set (reg:CC_Z CC_REGNUM)
6899 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
6900 (const_int 0)))
6901 (clobber (match_scratch:SI 1 "=r"))]
6902 "TARGET_32BIT"
6903 "orrs%?\\t%1, %Q0, %R0"
6904 [(set_attr "conds" "set")
6905 (set_attr "type" "logics_reg")]
6906 )
6907
6908 ; This insn allows redundant compares to be removed by cse, nothing should
6909 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6910 ; is deleted later on. The match_dup will match the mode here, so that
6911 ; mode changes of the condition codes aren't lost by this even though we don't
6912 ; specify what they are.
6913
6914 (define_insn "*deleted_compare"
6915 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6916 "TARGET_32BIT"
6917 "\\t%@ deleted compare"
6918 [(set_attr "conds" "set")
6919 (set_attr "length" "0")
6920 (set_attr "type" "no_insn")]
6921 )
6922
6923 \f
6924 ;; Conditional branch insns
6925
6926 (define_expand "cbranch_cc"
6927 [(set (pc)
6928 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
6929 (match_operand 2 "" "")])
6930 (label_ref (match_operand 3 "" ""))
6931 (pc)))]
6932 "TARGET_32BIT"
6933 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
6934 operands[1], operands[2], NULL_RTX);
6935 operands[2] = const0_rtx;"
6936 )
6937
6938 ;;
6939 ;; Patterns to match conditional branch insns.
6940 ;;
6941
6942 (define_insn "arm_cond_branch"
6943 [(set (pc)
6944 (if_then_else (match_operator 1 "arm_comparison_operator"
6945 [(match_operand 2 "cc_register" "") (const_int 0)])
6946 (label_ref (match_operand 0 "" ""))
6947 (pc)))]
6948 "TARGET_32BIT"
6949 "*
6950 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6951 {
6952 arm_ccfsm_state += 2;
6953 return \"\";
6954 }
6955 return \"b%d1\\t%l0\";
6956 "
6957 [(set_attr "conds" "use")
6958 (set_attr "type" "branch")
6959 (set (attr "length")
6960 (if_then_else
6961 (and (match_test "TARGET_THUMB2")
6962 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6963 (le (minus (match_dup 0) (pc)) (const_int 256))))
6964 (const_int 2)
6965 (const_int 4)))]
6966 )
6967
6968 (define_insn "*arm_cond_branch_reversed"
6969 [(set (pc)
6970 (if_then_else (match_operator 1 "arm_comparison_operator"
6971 [(match_operand 2 "cc_register" "") (const_int 0)])
6972 (pc)
6973 (label_ref (match_operand 0 "" ""))))]
6974 "TARGET_32BIT"
6975 "*
6976 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6977 {
6978 arm_ccfsm_state += 2;
6979 return \"\";
6980 }
6981 return \"b%D1\\t%l0\";
6982 "
6983 [(set_attr "conds" "use")
6984 (set_attr "type" "branch")
6985 (set (attr "length")
6986 (if_then_else
6987 (and (match_test "TARGET_THUMB2")
6988 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6989 (le (minus (match_dup 0) (pc)) (const_int 256))))
6990 (const_int 2)
6991 (const_int 4)))]
6992 )
6993
6994 \f
6995
6996 ; scc insns
6997
6998 (define_expand "cstore_cc"
6999 [(set (match_operand:SI 0 "s_register_operand")
7000 (match_operator:SI 1 "" [(match_operand 2 "" "")
7001 (match_operand 3 "" "")]))]
7002 "TARGET_32BIT"
7003 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7004 operands[2], operands[3], NULL_RTX);
7005 operands[3] = const0_rtx;"
7006 )
7007
7008 (define_insn_and_split "*mov_scc"
7009 [(set (match_operand:SI 0 "s_register_operand" "=r")
7010 (match_operator:SI 1 "arm_comparison_operator_mode"
7011 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7012 "TARGET_ARM"
7013 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7014 "TARGET_ARM"
7015 [(set (match_dup 0)
7016 (if_then_else:SI (match_dup 1)
7017 (const_int 1)
7018 (const_int 0)))]
7019 ""
7020 [(set_attr "conds" "use")
7021 (set_attr "length" "8")
7022 (set_attr "type" "multiple")]
7023 )
7024
7025 (define_insn_and_split "*mov_negscc"
7026 [(set (match_operand:SI 0 "s_register_operand" "=r")
7027 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
7028 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7029 "TARGET_ARM"
7030 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7031 "TARGET_ARM"
7032 [(set (match_dup 0)
7033 (if_then_else:SI (match_dup 1)
7034 (match_dup 3)
7035 (const_int 0)))]
7036 {
7037 operands[3] = GEN_INT (~0);
7038 }
7039 [(set_attr "conds" "use")
7040 (set_attr "length" "8")
7041 (set_attr "type" "multiple")]
7042 )
7043
7044 (define_insn_and_split "*mov_notscc"
7045 [(set (match_operand:SI 0 "s_register_operand" "=r")
7046 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7047 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7048 "TARGET_ARM"
7049 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7050 "TARGET_ARM"
7051 [(set (match_dup 0)
7052 (if_then_else:SI (match_dup 1)
7053 (match_dup 3)
7054 (match_dup 4)))]
7055 {
7056 operands[3] = GEN_INT (~1);
7057 operands[4] = GEN_INT (~0);
7058 }
7059 [(set_attr "conds" "use")
7060 (set_attr "length" "8")
7061 (set_attr "type" "multiple")]
7062 )
7063
7064 (define_expand "cstoresi4"
7065 [(set (match_operand:SI 0 "s_register_operand")
7066 (match_operator:SI 1 "expandable_comparison_operator"
7067 [(match_operand:SI 2 "s_register_operand")
7068 (match_operand:SI 3 "reg_or_int_operand")]))]
7069 "TARGET_32BIT || TARGET_THUMB1"
7070 "{
7071 rtx op3, scratch, scratch2;
7072
7073 if (!TARGET_THUMB1)
7074 {
7075 if (!arm_add_operand (operands[3], SImode))
7076 operands[3] = force_reg (SImode, operands[3]);
7077 emit_insn (gen_cstore_cc (operands[0], operands[1],
7078 operands[2], operands[3]));
7079 DONE;
7080 }
7081
7082 if (operands[3] == const0_rtx)
7083 {
7084 switch (GET_CODE (operands[1]))
7085 {
7086 case EQ:
7087 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7088 break;
7089
7090 case NE:
7091 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7092 break;
7093
7094 case LE:
7095 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7096 NULL_RTX, 0, OPTAB_WIDEN);
7097 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7098 NULL_RTX, 0, OPTAB_WIDEN);
7099 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7100 operands[0], 1, OPTAB_WIDEN);
7101 break;
7102
7103 case GE:
7104 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7105 NULL_RTX, 1);
7106 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7107 NULL_RTX, 1, OPTAB_WIDEN);
7108 break;
7109
7110 case GT:
7111 scratch = expand_binop (SImode, ashr_optab, operands[2],
7112 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7113 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7114 NULL_RTX, 0, OPTAB_WIDEN);
7115 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7116 0, OPTAB_WIDEN);
7117 break;
7118
7119 /* LT is handled by generic code. No need for unsigned with 0. */
7120 default:
7121 FAIL;
7122 }
7123 DONE;
7124 }
7125
7126 switch (GET_CODE (operands[1]))
7127 {
7128 case EQ:
7129 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7130 NULL_RTX, 0, OPTAB_WIDEN);
7131 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7132 break;
7133
7134 case NE:
7135 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7136 NULL_RTX, 0, OPTAB_WIDEN);
7137 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7138 break;
7139
7140 case LE:
7141 op3 = force_reg (SImode, operands[3]);
7142
7143 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7144 NULL_RTX, 1, OPTAB_WIDEN);
7145 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7146 NULL_RTX, 0, OPTAB_WIDEN);
7147 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7148 op3, operands[2]));
7149 break;
7150
7151 case GE:
7152 op3 = operands[3];
7153 if (!thumb1_cmp_operand (op3, SImode))
7154 op3 = force_reg (SImode, op3);
7155 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7156 NULL_RTX, 0, OPTAB_WIDEN);
7157 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7158 NULL_RTX, 1, OPTAB_WIDEN);
7159 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7160 operands[2], op3));
7161 break;
7162
7163 case LEU:
7164 op3 = force_reg (SImode, operands[3]);
7165 scratch = force_reg (SImode, const0_rtx);
7166 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7167 op3, operands[2]));
7168 break;
7169
7170 case GEU:
7171 op3 = operands[3];
7172 if (!thumb1_cmp_operand (op3, SImode))
7173 op3 = force_reg (SImode, op3);
7174 scratch = force_reg (SImode, const0_rtx);
7175 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7176 operands[2], op3));
7177 break;
7178
7179 case LTU:
7180 op3 = operands[3];
7181 if (!thumb1_cmp_operand (op3, SImode))
7182 op3 = force_reg (SImode, op3);
7183 scratch = gen_reg_rtx (SImode);
7184 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7185 break;
7186
7187 case GTU:
7188 op3 = force_reg (SImode, operands[3]);
7189 scratch = gen_reg_rtx (SImode);
7190 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7191 break;
7192
7193 /* No good sequences for GT, LT. */
7194 default:
7195 FAIL;
7196 }
7197 DONE;
7198 }")
7199
7200 (define_expand "cstorehf4"
7201 [(set (match_operand:SI 0 "s_register_operand")
7202 (match_operator:SI 1 "expandable_comparison_operator"
7203 [(match_operand:HF 2 "s_register_operand")
7204 (match_operand:HF 3 "vfp_compare_operand")]))]
7205 "TARGET_VFP_FP16INST"
7206 {
7207 if (!arm_validize_comparison (&operands[1],
7208 &operands[2],
7209 &operands[3]))
7210 FAIL;
7211
7212 emit_insn (gen_cstore_cc (operands[0], operands[1],
7213 operands[2], operands[3]));
7214 DONE;
7215 }
7216 )
7217
7218 (define_expand "cstoresf4"
7219 [(set (match_operand:SI 0 "s_register_operand")
7220 (match_operator:SI 1 "expandable_comparison_operator"
7221 [(match_operand:SF 2 "s_register_operand")
7222 (match_operand:SF 3 "vfp_compare_operand")]))]
7223 "TARGET_32BIT && TARGET_HARD_FLOAT"
7224 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7225 operands[2], operands[3])); DONE;"
7226 )
7227
7228 (define_expand "cstoredf4"
7229 [(set (match_operand:SI 0 "s_register_operand")
7230 (match_operator:SI 1 "expandable_comparison_operator"
7231 [(match_operand:DF 2 "s_register_operand")
7232 (match_operand:DF 3 "vfp_compare_operand")]))]
7233 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7234 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7235 operands[2], operands[3])); DONE;"
7236 )
7237
7238 (define_expand "cstoredi4"
7239 [(set (match_operand:SI 0 "s_register_operand")
7240 (match_operator:SI 1 "expandable_comparison_operator"
7241 [(match_operand:DI 2 "s_register_operand")
7242 (match_operand:DI 3 "cmpdi_operand")]))]
7243 "TARGET_32BIT"
7244 "{
7245 if (!arm_validize_comparison (&operands[1],
7246 &operands[2],
7247 &operands[3]))
7248 FAIL;
7249 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7250 operands[3]));
7251 DONE;
7252 }"
7253 )
7254
7255 \f
7256 ;; Conditional move insns
7257
7258 (define_expand "movsicc"
7259 [(set (match_operand:SI 0 "s_register_operand")
7260 (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
7261 (match_operand:SI 2 "arm_not_operand")
7262 (match_operand:SI 3 "arm_not_operand")))]
7263 "TARGET_32BIT"
7264 "
7265 {
7266 enum rtx_code code;
7267 rtx ccreg;
7268
7269 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7270 &XEXP (operands[1], 1)))
7271 FAIL;
7272
7273 code = GET_CODE (operands[1]);
7274 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7275 XEXP (operands[1], 1), NULL_RTX);
7276 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7277 }"
7278 )
7279
7280 (define_expand "movhfcc"
7281 [(set (match_operand:HF 0 "s_register_operand")
7282 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7283 (match_operand:HF 2 "s_register_operand")
7284 (match_operand:HF 3 "s_register_operand")))]
7285 "TARGET_VFP_FP16INST"
7286 "
7287 {
7288 enum rtx_code code = GET_CODE (operands[1]);
7289 rtx ccreg;
7290
7291 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7292 &XEXP (operands[1], 1)))
7293 FAIL;
7294
7295 code = GET_CODE (operands[1]);
7296 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7297 XEXP (operands[1], 1), NULL_RTX);
7298 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7299 }"
7300 )
7301
7302 (define_expand "movsfcc"
7303 [(set (match_operand:SF 0 "s_register_operand")
7304 (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
7305 (match_operand:SF 2 "s_register_operand")
7306 (match_operand:SF 3 "s_register_operand")))]
7307 "TARGET_32BIT && TARGET_HARD_FLOAT"
7308 "
7309 {
7310 enum rtx_code code = GET_CODE (operands[1]);
7311 rtx ccreg;
7312
7313 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7314 &XEXP (operands[1], 1)))
7315 FAIL;
7316
7317 code = GET_CODE (operands[1]);
7318 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7319 XEXP (operands[1], 1), NULL_RTX);
7320 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7321 }"
7322 )
7323
7324 (define_expand "movdfcc"
7325 [(set (match_operand:DF 0 "s_register_operand")
7326 (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
7327 (match_operand:DF 2 "s_register_operand")
7328 (match_operand:DF 3 "s_register_operand")))]
7329 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7330 "
7331 {
7332 enum rtx_code code = GET_CODE (operands[1]);
7333 rtx ccreg;
7334
7335 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7336 &XEXP (operands[1], 1)))
7337 FAIL;
7338 code = GET_CODE (operands[1]);
7339 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7340 XEXP (operands[1], 1), NULL_RTX);
7341 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7342 }"
7343 )
7344
7345 (define_insn "*cmov<mode>"
7346 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7347 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7348 [(match_operand 2 "cc_register" "") (const_int 0)])
7349 (match_operand:SDF 3 "s_register_operand"
7350 "<F_constraint>")
7351 (match_operand:SDF 4 "s_register_operand"
7352 "<F_constraint>")))]
7353 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
7354 "*
7355 {
7356 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7357 switch (code)
7358 {
7359 case ARM_GE:
7360 case ARM_GT:
7361 case ARM_EQ:
7362 case ARM_VS:
7363 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7364 case ARM_LT:
7365 case ARM_LE:
7366 case ARM_NE:
7367 case ARM_VC:
7368 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7369 default:
7370 gcc_unreachable ();
7371 }
7372 return \"\";
7373 }"
7374 [(set_attr "conds" "use")
7375 (set_attr "type" "fcsel")]
7376 )
7377
7378 (define_insn "*cmovhf"
7379 [(set (match_operand:HF 0 "s_register_operand" "=t")
7380 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7381 [(match_operand 2 "cc_register" "") (const_int 0)])
7382 (match_operand:HF 3 "s_register_operand" "t")
7383 (match_operand:HF 4 "s_register_operand" "t")))]
7384 "TARGET_VFP_FP16INST"
7385 "*
7386 {
7387 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7388 switch (code)
7389 {
7390 case ARM_GE:
7391 case ARM_GT:
7392 case ARM_EQ:
7393 case ARM_VS:
7394 return \"vsel%d1.f16\\t%0, %3, %4\";
7395 case ARM_LT:
7396 case ARM_LE:
7397 case ARM_NE:
7398 case ARM_VC:
7399 return \"vsel%D1.f16\\t%0, %4, %3\";
7400 default:
7401 gcc_unreachable ();
7402 }
7403 return \"\";
7404 }"
7405 [(set_attr "conds" "use")
7406 (set_attr "type" "fcsel")]
7407 )
7408
7409 (define_insn_and_split "*movsicc_insn"
7410 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7411 (if_then_else:SI
7412 (match_operator 3 "arm_comparison_operator"
7413 [(match_operand 4 "cc_register" "") (const_int 0)])
7414 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7415 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7416 "TARGET_ARM"
7417 "@
7418 mov%D3\\t%0, %2
7419 mvn%D3\\t%0, #%B2
7420 mov%d3\\t%0, %1
7421 mvn%d3\\t%0, #%B1
7422 #
7423 #
7424 #
7425 #"
7426 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7427 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7428 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7429 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7430 "&& reload_completed"
7431 [(const_int 0)]
7432 {
7433 enum rtx_code rev_code;
7434 machine_mode mode;
7435 rtx rev_cond;
7436
7437 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7438 operands[3],
7439 gen_rtx_SET (operands[0], operands[1])));
7440
7441 rev_code = GET_CODE (operands[3]);
7442 mode = GET_MODE (operands[4]);
7443 if (mode == CCFPmode || mode == CCFPEmode)
7444 rev_code = reverse_condition_maybe_unordered (rev_code);
7445 else
7446 rev_code = reverse_condition (rev_code);
7447
7448 rev_cond = gen_rtx_fmt_ee (rev_code,
7449 VOIDmode,
7450 operands[4],
7451 const0_rtx);
7452 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7453 rev_cond,
7454 gen_rtx_SET (operands[0], operands[2])));
7455 DONE;
7456 }
7457 [(set_attr "length" "4,4,4,4,8,8,8,8")
7458 (set_attr "conds" "use")
7459 (set_attr_alternative "type"
7460 [(if_then_else (match_operand 2 "const_int_operand" "")
7461 (const_string "mov_imm")
7462 (const_string "mov_reg"))
7463 (const_string "mvn_imm")
7464 (if_then_else (match_operand 1 "const_int_operand" "")
7465 (const_string "mov_imm")
7466 (const_string "mov_reg"))
7467 (const_string "mvn_imm")
7468 (const_string "multiple")
7469 (const_string "multiple")
7470 (const_string "multiple")
7471 (const_string "multiple")])]
7472 )
7473
7474 (define_insn "*movsfcc_soft_insn"
7475 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7476 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7477 [(match_operand 4 "cc_register" "") (const_int 0)])
7478 (match_operand:SF 1 "s_register_operand" "0,r")
7479 (match_operand:SF 2 "s_register_operand" "r,0")))]
7480 "TARGET_ARM && TARGET_SOFT_FLOAT"
7481 "@
7482 mov%D3\\t%0, %2
7483 mov%d3\\t%0, %1"
7484 [(set_attr "conds" "use")
7485 (set_attr "type" "mov_reg")]
7486 )
7487
7488 \f
7489 ;; Jump and linkage insns
7490
7491 (define_expand "jump"
7492 [(set (pc)
7493 (label_ref (match_operand 0 "" "")))]
7494 "TARGET_EITHER"
7495 ""
7496 )
7497
7498 (define_insn "*arm_jump"
7499 [(set (pc)
7500 (label_ref (match_operand 0 "" "")))]
7501 "TARGET_32BIT"
7502 "*
7503 {
7504 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7505 {
7506 arm_ccfsm_state += 2;
7507 return \"\";
7508 }
7509 return \"b%?\\t%l0\";
7510 }
7511 "
7512 [(set_attr "predicable" "yes")
7513 (set (attr "length")
7514 (if_then_else
7515 (and (match_test "TARGET_THUMB2")
7516 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7517 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7518 (const_int 2)
7519 (const_int 4)))
7520 (set_attr "type" "branch")]
7521 )
7522
7523 (define_expand "call"
7524 [(parallel [(call (match_operand 0 "memory_operand")
7525 (match_operand 1 "general_operand"))
7526 (use (match_operand 2 "" ""))
7527 (clobber (reg:SI LR_REGNUM))])]
7528 "TARGET_EITHER"
7529 "
7530 {
7531 rtx callee, pat;
7532 tree addr = MEM_EXPR (operands[0]);
7533
7534 /* In an untyped call, we can get NULL for operand 2. */
7535 if (operands[2] == NULL_RTX)
7536 operands[2] = const0_rtx;
7537
7538 /* Decide if we should generate indirect calls by loading the
7539 32-bit address of the callee into a register before performing the
7540 branch and link. */
7541 callee = XEXP (operands[0], 0);
7542 if (GET_CODE (callee) == SYMBOL_REF
7543 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7544 : !REG_P (callee))
7545 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7546
7547 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[0], 0)))
7548 /* Indirect call: set r9 with FDPIC value of callee. */
7549 XEXP (operands[0], 0)
7550 = arm_load_function_descriptor (XEXP (operands[0], 0));
7551
7552 if (detect_cmse_nonsecure_call (addr))
7553 {
7554 pat = gen_nonsecure_call_internal (operands[0], operands[1],
7555 operands[2]);
7556 emit_call_insn (pat);
7557 }
7558 else
7559 {
7560 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7561 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
7562 }
7563
7564 /* Restore FDPIC register (r9) after call. */
7565 if (TARGET_FDPIC)
7566 {
7567 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7568 rtx initial_fdpic_reg
7569 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7570
7571 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7572 initial_fdpic_reg));
7573 }
7574
7575 DONE;
7576 }"
7577 )
7578
7579 (define_insn "restore_pic_register_after_call"
7580 [(set (match_operand:SI 0 "s_register_operand" "+r,r")
7581 (unspec:SI [(match_dup 0)
7582 (match_operand:SI 1 "nonimmediate_operand" "r,m")]
7583 UNSPEC_PIC_RESTORE))]
7584 ""
7585 "@
7586 mov\t%0, %1
7587 ldr\t%0, %1"
7588 )
7589
7590 (define_expand "call_internal"
7591 [(parallel [(call (match_operand 0 "memory_operand")
7592 (match_operand 1 "general_operand"))
7593 (use (match_operand 2 "" ""))
7594 (clobber (reg:SI LR_REGNUM))])])
7595
7596 (define_expand "nonsecure_call_internal"
7597 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
7598 UNSPEC_NONSECURE_MEM)
7599 (match_operand 1 "general_operand"))
7600 (use (match_operand 2 "" ""))
7601 (clobber (reg:SI LR_REGNUM))])]
7602 "use_cmse"
7603 "
7604 {
7605 rtx tmp;
7606 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
7607 gen_rtx_REG (SImode, R4_REGNUM),
7608 SImode);
7609
7610 operands[0] = replace_equiv_address (operands[0], tmp);
7611 }")
7612
7613 (define_insn "*call_reg_armv5"
7614 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7615 (match_operand 1 "" ""))
7616 (use (match_operand 2 "" ""))
7617 (clobber (reg:SI LR_REGNUM))]
7618 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
7619 "blx%?\\t%0"
7620 [(set_attr "type" "call")]
7621 )
7622
7623 (define_insn "*call_reg_arm"
7624 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7625 (match_operand 1 "" ""))
7626 (use (match_operand 2 "" ""))
7627 (clobber (reg:SI LR_REGNUM))]
7628 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
7629 "*
7630 return output_call (operands);
7631 "
7632 ;; length is worst case, normally it is only two
7633 [(set_attr "length" "12")
7634 (set_attr "type" "call")]
7635 )
7636
7637
7638 (define_expand "call_value"
7639 [(parallel [(set (match_operand 0 "" "")
7640 (call (match_operand 1 "memory_operand")
7641 (match_operand 2 "general_operand")))
7642 (use (match_operand 3 "" ""))
7643 (clobber (reg:SI LR_REGNUM))])]
7644 "TARGET_EITHER"
7645 "
7646 {
7647 rtx pat, callee;
7648 tree addr = MEM_EXPR (operands[1]);
7649
7650 /* In an untyped call, we can get NULL for operand 2. */
7651 if (operands[3] == 0)
7652 operands[3] = const0_rtx;
7653
7654 /* Decide if we should generate indirect calls by loading the
7655 32-bit address of the callee into a register before performing the
7656 branch and link. */
7657 callee = XEXP (operands[1], 0);
7658 if (GET_CODE (callee) == SYMBOL_REF
7659 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7660 : !REG_P (callee))
7661 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7662
7663 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[1], 0)))
7664 /* Indirect call: set r9 with FDPIC value of callee. */
7665 XEXP (operands[1], 0)
7666 = arm_load_function_descriptor (XEXP (operands[1], 0));
7667
7668 if (detect_cmse_nonsecure_call (addr))
7669 {
7670 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
7671 operands[2], operands[3]);
7672 emit_call_insn (pat);
7673 }
7674 else
7675 {
7676 pat = gen_call_value_internal (operands[0], operands[1],
7677 operands[2], operands[3]);
7678 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
7679 }
7680
7681 /* Restore FDPIC register (r9) after call. */
7682 if (TARGET_FDPIC)
7683 {
7684 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7685 rtx initial_fdpic_reg
7686 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7687
7688 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7689 initial_fdpic_reg));
7690 }
7691
7692 DONE;
7693 }"
7694 )
7695
7696 (define_expand "call_value_internal"
7697 [(parallel [(set (match_operand 0 "" "")
7698 (call (match_operand 1 "memory_operand")
7699 (match_operand 2 "general_operand")))
7700 (use (match_operand 3 "" ""))
7701 (clobber (reg:SI LR_REGNUM))])])
7702
7703 (define_expand "nonsecure_call_value_internal"
7704 [(parallel [(set (match_operand 0 "" "")
7705 (call (unspec:SI [(match_operand 1 "memory_operand")]
7706 UNSPEC_NONSECURE_MEM)
7707 (match_operand 2 "general_operand")))
7708 (use (match_operand 3 "" ""))
7709 (clobber (reg:SI LR_REGNUM))])]
7710 "use_cmse"
7711 "
7712 {
7713 rtx tmp;
7714 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
7715 gen_rtx_REG (SImode, R4_REGNUM),
7716 SImode);
7717
7718 operands[1] = replace_equiv_address (operands[1], tmp);
7719 }")
7720
7721 (define_insn "*call_value_reg_armv5"
7722 [(set (match_operand 0 "" "")
7723 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7724 (match_operand 2 "" "")))
7725 (use (match_operand 3 "" ""))
7726 (clobber (reg:SI LR_REGNUM))]
7727 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
7728 "blx%?\\t%1"
7729 [(set_attr "type" "call")]
7730 )
7731
7732 (define_insn "*call_value_reg_arm"
7733 [(set (match_operand 0 "" "")
7734 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7735 (match_operand 2 "" "")))
7736 (use (match_operand 3 "" ""))
7737 (clobber (reg:SI LR_REGNUM))]
7738 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
7739 "*
7740 return output_call (&operands[1]);
7741 "
7742 [(set_attr "length" "12")
7743 (set_attr "type" "call")]
7744 )
7745
7746 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7747 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7748
7749 (define_insn "*call_symbol"
7750 [(call (mem:SI (match_operand:SI 0 "" ""))
7751 (match_operand 1 "" ""))
7752 (use (match_operand 2 "" ""))
7753 (clobber (reg:SI LR_REGNUM))]
7754 "TARGET_32BIT
7755 && !SIBLING_CALL_P (insn)
7756 && (GET_CODE (operands[0]) == SYMBOL_REF)
7757 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
7758 "*
7759 {
7760 rtx op = operands[0];
7761
7762 /* Switch mode now when possible. */
7763 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7764 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7765 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7766
7767 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7768 }"
7769 [(set_attr "type" "call")]
7770 )
7771
7772 (define_insn "*call_value_symbol"
7773 [(set (match_operand 0 "" "")
7774 (call (mem:SI (match_operand:SI 1 "" ""))
7775 (match_operand:SI 2 "" "")))
7776 (use (match_operand 3 "" ""))
7777 (clobber (reg:SI LR_REGNUM))]
7778 "TARGET_32BIT
7779 && !SIBLING_CALL_P (insn)
7780 && (GET_CODE (operands[1]) == SYMBOL_REF)
7781 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
7782 "*
7783 {
7784 rtx op = operands[1];
7785
7786 /* Switch mode now when possible. */
7787 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7788 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7789 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
7790
7791 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7792 }"
7793 [(set_attr "type" "call")]
7794 )
7795
7796 (define_expand "sibcall_internal"
7797 [(parallel [(call (match_operand 0 "memory_operand")
7798 (match_operand 1 "general_operand"))
7799 (return)
7800 (use (match_operand 2 "" ""))])])
7801
7802 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7803 (define_expand "sibcall"
7804 [(parallel [(call (match_operand 0 "memory_operand")
7805 (match_operand 1 "general_operand"))
7806 (return)
7807 (use (match_operand 2 "" ""))])]
7808 "TARGET_32BIT"
7809 "
7810 {
7811 rtx pat;
7812
7813 if ((!REG_P (XEXP (operands[0], 0))
7814 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7815 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7816 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
7817 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7818
7819 if (operands[2] == NULL_RTX)
7820 operands[2] = const0_rtx;
7821
7822 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7823 arm_emit_call_insn (pat, operands[0], true);
7824 DONE;
7825 }"
7826 )
7827
7828 (define_expand "sibcall_value_internal"
7829 [(parallel [(set (match_operand 0 "" "")
7830 (call (match_operand 1 "memory_operand")
7831 (match_operand 2 "general_operand")))
7832 (return)
7833 (use (match_operand 3 "" ""))])])
7834
7835 (define_expand "sibcall_value"
7836 [(parallel [(set (match_operand 0 "" "")
7837 (call (match_operand 1 "memory_operand")
7838 (match_operand 2 "general_operand")))
7839 (return)
7840 (use (match_operand 3 "" ""))])]
7841 "TARGET_32BIT"
7842 "
7843 {
7844 rtx pat;
7845
7846 if ((!REG_P (XEXP (operands[1], 0))
7847 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7848 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7849 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
7850 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7851
7852 if (operands[3] == NULL_RTX)
7853 operands[3] = const0_rtx;
7854
7855 pat = gen_sibcall_value_internal (operands[0], operands[1],
7856 operands[2], operands[3]);
7857 arm_emit_call_insn (pat, operands[1], true);
7858 DONE;
7859 }"
7860 )
7861
7862 (define_insn "*sibcall_insn"
7863 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
7864 (match_operand 1 "" ""))
7865 (return)
7866 (use (match_operand 2 "" ""))]
7867 "TARGET_32BIT && SIBLING_CALL_P (insn)"
7868 "*
7869 if (which_alternative == 1)
7870 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7871 else
7872 {
7873 if (arm_arch5t || arm_arch4t)
7874 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
7875 else
7876 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7877 }
7878 "
7879 [(set_attr "type" "call")]
7880 )
7881
7882 (define_insn "*sibcall_value_insn"
7883 [(set (match_operand 0 "" "")
7884 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
7885 (match_operand 2 "" "")))
7886 (return)
7887 (use (match_operand 3 "" ""))]
7888 "TARGET_32BIT && SIBLING_CALL_P (insn)"
7889 "*
7890 if (which_alternative == 1)
7891 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7892 else
7893 {
7894 if (arm_arch5t || arm_arch4t)
7895 return \"bx%?\\t%1\";
7896 else
7897 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7898 }
7899 "
7900 [(set_attr "type" "call")]
7901 )
7902
7903 (define_expand "<return_str>return"
7904 [(RETURNS)]
7905 "(TARGET_ARM || (TARGET_THUMB2
7906 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7907 && !IS_STACKALIGN (arm_current_func_type ())))
7908 <return_cond_false>"
7909 "
7910 {
7911 if (TARGET_THUMB2)
7912 {
7913 thumb2_expand_return (<return_simple_p>);
7914 DONE;
7915 }
7916 }
7917 "
7918 )
7919
7920 ;; Often the return insn will be the same as loading from memory, so set attr
7921 (define_insn "*arm_return"
7922 [(return)]
7923 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7924 "*
7925 {
7926 if (arm_ccfsm_state == 2)
7927 {
7928 arm_ccfsm_state += 2;
7929 return \"\";
7930 }
7931 return output_return_instruction (const_true_rtx, true, false, false);
7932 }"
7933 [(set_attr "type" "load_4")
7934 (set_attr "length" "12")
7935 (set_attr "predicable" "yes")]
7936 )
7937
7938 (define_insn "*cond_<return_str>return"
7939 [(set (pc)
7940 (if_then_else (match_operator 0 "arm_comparison_operator"
7941 [(match_operand 1 "cc_register" "") (const_int 0)])
7942 (RETURNS)
7943 (pc)))]
7944 "TARGET_ARM <return_cond_true>"
7945 "*
7946 {
7947 if (arm_ccfsm_state == 2)
7948 {
7949 arm_ccfsm_state += 2;
7950 return \"\";
7951 }
7952 return output_return_instruction (operands[0], true, false,
7953 <return_simple_p>);
7954 }"
7955 [(set_attr "conds" "use")
7956 (set_attr "length" "12")
7957 (set_attr "type" "load_4")]
7958 )
7959
7960 (define_insn "*cond_<return_str>return_inverted"
7961 [(set (pc)
7962 (if_then_else (match_operator 0 "arm_comparison_operator"
7963 [(match_operand 1 "cc_register" "") (const_int 0)])
7964 (pc)
7965 (RETURNS)))]
7966 "TARGET_ARM <return_cond_true>"
7967 "*
7968 {
7969 if (arm_ccfsm_state == 2)
7970 {
7971 arm_ccfsm_state += 2;
7972 return \"\";
7973 }
7974 return output_return_instruction (operands[0], true, true,
7975 <return_simple_p>);
7976 }"
7977 [(set_attr "conds" "use")
7978 (set_attr "length" "12")
7979 (set_attr "type" "load_4")]
7980 )
7981
7982 (define_insn "*arm_simple_return"
7983 [(simple_return)]
7984 "TARGET_ARM"
7985 "*
7986 {
7987 if (arm_ccfsm_state == 2)
7988 {
7989 arm_ccfsm_state += 2;
7990 return \"\";
7991 }
7992 return output_return_instruction (const_true_rtx, true, false, true);
7993 }"
7994 [(set_attr "type" "branch")
7995 (set_attr "length" "4")
7996 (set_attr "predicable" "yes")]
7997 )
7998
7999 ;; Generate a sequence of instructions to determine if the processor is
8000 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8001 ;; mask.
8002
8003 (define_expand "return_addr_mask"
8004 [(set (match_dup 1)
8005 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8006 (const_int 0)))
8007 (set (match_operand:SI 0 "s_register_operand")
8008 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8009 (const_int -1)
8010 (const_int 67108860)))] ; 0x03fffffc
8011 "TARGET_ARM"
8012 "
8013 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8014 ")
8015
8016 (define_insn "*check_arch2"
8017 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8018 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8019 (const_int 0)))]
8020 "TARGET_ARM"
8021 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8022 [(set_attr "length" "8")
8023 (set_attr "conds" "set")
8024 (set_attr "type" "multiple")]
8025 )
8026
8027 ;; Call subroutine returning any type.
8028
8029 (define_expand "untyped_call"
8030 [(parallel [(call (match_operand 0 "" "")
8031 (const_int 0))
8032 (match_operand 1 "" "")
8033 (match_operand 2 "" "")])]
8034 "TARGET_EITHER && !TARGET_FDPIC"
8035 "
8036 {
8037 int i;
8038 rtx par = gen_rtx_PARALLEL (VOIDmode,
8039 rtvec_alloc (XVECLEN (operands[2], 0)));
8040 rtx addr = gen_reg_rtx (Pmode);
8041 rtx mem;
8042 int size = 0;
8043
8044 emit_move_insn (addr, XEXP (operands[1], 0));
8045 mem = change_address (operands[1], BLKmode, addr);
8046
8047 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8048 {
8049 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8050
8051 /* Default code only uses r0 as a return value, but we could
8052 be using anything up to 4 registers. */
8053 if (REGNO (src) == R0_REGNUM)
8054 src = gen_rtx_REG (TImode, R0_REGNUM);
8055
8056 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8057 GEN_INT (size));
8058 size += GET_MODE_SIZE (GET_MODE (src));
8059 }
8060
8061 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
8062
8063 size = 0;
8064
8065 for (i = 0; i < XVECLEN (par, 0); i++)
8066 {
8067 HOST_WIDE_INT offset = 0;
8068 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8069
8070 if (size != 0)
8071 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8072
8073 mem = change_address (mem, GET_MODE (reg), NULL);
8074 if (REGNO (reg) == R0_REGNUM)
8075 {
8076 /* On thumb we have to use a write-back instruction. */
8077 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8078 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8079 size = TARGET_ARM ? 16 : 0;
8080 }
8081 else
8082 {
8083 emit_move_insn (mem, reg);
8084 size = GET_MODE_SIZE (GET_MODE (reg));
8085 }
8086 }
8087
8088 /* The optimizer does not know that the call sets the function value
8089 registers we stored in the result block. We avoid problems by
8090 claiming that all hard registers are used and clobbered at this
8091 point. */
8092 emit_insn (gen_blockage ());
8093
8094 DONE;
8095 }"
8096 )
8097
8098 (define_expand "untyped_return"
8099 [(match_operand:BLK 0 "memory_operand")
8100 (match_operand 1 "" "")]
8101 "TARGET_EITHER && !TARGET_FDPIC"
8102 "
8103 {
8104 int i;
8105 rtx addr = gen_reg_rtx (Pmode);
8106 rtx mem;
8107 int size = 0;
8108
8109 emit_move_insn (addr, XEXP (operands[0], 0));
8110 mem = change_address (operands[0], BLKmode, addr);
8111
8112 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8113 {
8114 HOST_WIDE_INT offset = 0;
8115 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8116
8117 if (size != 0)
8118 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8119
8120 mem = change_address (mem, GET_MODE (reg), NULL);
8121 if (REGNO (reg) == R0_REGNUM)
8122 {
8123 /* On thumb we have to use a write-back instruction. */
8124 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8125 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8126 size = TARGET_ARM ? 16 : 0;
8127 }
8128 else
8129 {
8130 emit_move_insn (reg, mem);
8131 size = GET_MODE_SIZE (GET_MODE (reg));
8132 }
8133 }
8134
8135 /* Emit USE insns before the return. */
8136 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8137 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8138
8139 /* Construct the return. */
8140 expand_naked_return ();
8141
8142 DONE;
8143 }"
8144 )
8145
8146 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8147 ;; all of memory. This blocks insns from being moved across this point.
8148
8149 (define_insn "blockage"
8150 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8151 "TARGET_EITHER"
8152 ""
8153 [(set_attr "length" "0")
8154 (set_attr "type" "block")]
8155 )
8156
8157 ;; Since we hard code r0 here use the 'o' constraint to prevent
8158 ;; provoking undefined behaviour in the hardware with putting out
8159 ;; auto-increment operations with potentially r0 as the base register.
8160 (define_insn "probe_stack"
8161 [(set (match_operand:SI 0 "memory_operand" "=o")
8162 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
8163 "TARGET_32BIT"
8164 "str%?\\tr0, %0"
8165 [(set_attr "type" "store_4")
8166 (set_attr "predicable" "yes")]
8167 )
8168
8169 (define_insn "probe_stack_range"
8170 [(set (match_operand:SI 0 "register_operand" "=r")
8171 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8172 (match_operand:SI 2 "register_operand" "r")]
8173 VUNSPEC_PROBE_STACK_RANGE))]
8174 "TARGET_32BIT"
8175 {
8176 return output_probe_stack_range (operands[0], operands[2]);
8177 }
8178 [(set_attr "type" "multiple")
8179 (set_attr "conds" "clob")]
8180 )
8181
8182 ;; Named patterns for stack smashing protection.
8183 (define_expand "stack_protect_combined_set"
8184 [(parallel
8185 [(set (match_operand:SI 0 "memory_operand")
8186 (unspec:SI [(match_operand:SI 1 "guard_operand")]
8187 UNSPEC_SP_SET))
8188 (clobber (match_scratch:SI 2 ""))
8189 (clobber (match_scratch:SI 3 ""))])]
8190 ""
8191 ""
8192 )
8193
8194 ;; Use a separate insn from the above expand to be able to have the mem outside
8195 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8196 ;; try to reload the guard since we need to control how PIC access is done in
8197 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8198 ;; legitimize_pic_address ()).
8199 (define_insn_and_split "*stack_protect_combined_set_insn"
8200 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8201 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8202 UNSPEC_SP_SET))
8203 (clobber (match_scratch:SI 2 "=&l,&r"))
8204 (clobber (match_scratch:SI 3 "=&l,&r"))]
8205 ""
8206 "#"
8207 "reload_completed"
8208 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8209 UNSPEC_SP_SET))
8210 (clobber (match_dup 2))])]
8211 "
8212 {
8213 if (flag_pic)
8214 {
8215 rtx pic_reg;
8216
8217 if (TARGET_FDPIC)
8218 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8219 else
8220 pic_reg = operands[3];
8221
8222 /* Forces recomputing of GOT base now. */
8223 legitimize_pic_address (operands[1], SImode, operands[2], pic_reg,
8224 true /*compute_now*/);
8225 }
8226 else
8227 {
8228 if (address_operand (operands[1], SImode))
8229 operands[2] = operands[1];
8230 else
8231 {
8232 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8233 emit_move_insn (operands[2], mem);
8234 }
8235 }
8236 }"
8237 [(set_attr "arch" "t1,32")]
8238 )
8239
8240 ;; DO NOT SPLIT THIS INSN. It's important for security reasons that the
8241 ;; canary value does not live beyond the life of this sequence.
8242 (define_insn "*stack_protect_set_insn"
8243 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8244 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8245 UNSPEC_SP_SET))
8246 (clobber (match_dup 1))]
8247 ""
8248 "@
8249 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1, #0
8250 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1, #0"
8251 [(set_attr "length" "8,12")
8252 (set_attr "conds" "clob,nocond")
8253 (set_attr "type" "multiple")
8254 (set_attr "arch" "t1,32")]
8255 )
8256
8257 (define_expand "stack_protect_combined_test"
8258 [(parallel
8259 [(set (pc)
8260 (if_then_else
8261 (eq (match_operand:SI 0 "memory_operand")
8262 (unspec:SI [(match_operand:SI 1 "guard_operand")]
8263 UNSPEC_SP_TEST))
8264 (label_ref (match_operand 2))
8265 (pc)))
8266 (clobber (match_scratch:SI 3 ""))
8267 (clobber (match_scratch:SI 4 ""))
8268 (clobber (reg:CC CC_REGNUM))])]
8269 ""
8270 ""
8271 )
8272
8273 ;; Use a separate insn from the above expand to be able to have the mem outside
8274 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8275 ;; try to reload the guard since we need to control how PIC access is done in
8276 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8277 ;; legitimize_pic_address ()).
8278 (define_insn_and_split "*stack_protect_combined_test_insn"
8279 [(set (pc)
8280 (if_then_else
8281 (eq (match_operand:SI 0 "memory_operand" "m,m")
8282 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8283 UNSPEC_SP_TEST))
8284 (label_ref (match_operand 2))
8285 (pc)))
8286 (clobber (match_scratch:SI 3 "=&l,&r"))
8287 (clobber (match_scratch:SI 4 "=&l,&r"))
8288 (clobber (reg:CC CC_REGNUM))]
8289 ""
8290 "#"
8291 "reload_completed"
8292 [(const_int 0)]
8293 {
8294 rtx eq;
8295
8296 if (flag_pic)
8297 {
8298 rtx pic_reg;
8299
8300 if (TARGET_FDPIC)
8301 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8302 else
8303 pic_reg = operands[4];
8304
8305 /* Forces recomputing of GOT base now. */
8306 legitimize_pic_address (operands[1], SImode, operands[3], pic_reg,
8307 true /*compute_now*/);
8308 }
8309 else
8310 {
8311 if (address_operand (operands[1], SImode))
8312 operands[3] = operands[1];
8313 else
8314 {
8315 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8316 emit_move_insn (operands[3], mem);
8317 }
8318 }
8319 if (TARGET_32BIT)
8320 {
8321 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8322 operands[3]));
8323 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8324 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8325 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8326 }
8327 else
8328 {
8329 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8330 operands[3]));
8331 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8332 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8333 operands[2]));
8334 }
8335 DONE;
8336 }
8337 [(set_attr "arch" "t1,32")]
8338 )
8339
8340 (define_insn "arm_stack_protect_test_insn"
8341 [(set (reg:CC_Z CC_REGNUM)
8342 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8343 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8344 UNSPEC_SP_TEST)
8345 (const_int 0)))
8346 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8347 (clobber (match_dup 2))]
8348 "TARGET_32BIT"
8349 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8350 [(set_attr "length" "8,12")
8351 (set_attr "conds" "set")
8352 (set_attr "type" "multiple")
8353 (set_attr "arch" "t,32")]
8354 )
8355
8356 (define_expand "casesi"
8357 [(match_operand:SI 0 "s_register_operand") ; index to jump on
8358 (match_operand:SI 1 "const_int_operand") ; lower bound
8359 (match_operand:SI 2 "const_int_operand") ; total range
8360 (match_operand:SI 3 "" "") ; table label
8361 (match_operand:SI 4 "" "")] ; Out of range label
8362 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
8363 "
8364 {
8365 enum insn_code code;
8366 if (operands[1] != const0_rtx)
8367 {
8368 rtx reg = gen_reg_rtx (SImode);
8369
8370 emit_insn (gen_addsi3 (reg, operands[0],
8371 gen_int_mode (-INTVAL (operands[1]),
8372 SImode)));
8373 operands[0] = reg;
8374 }
8375
8376 if (TARGET_ARM)
8377 code = CODE_FOR_arm_casesi_internal;
8378 else if (TARGET_THUMB1)
8379 code = CODE_FOR_thumb1_casesi_internal_pic;
8380 else if (flag_pic)
8381 code = CODE_FOR_thumb2_casesi_internal_pic;
8382 else
8383 code = CODE_FOR_thumb2_casesi_internal;
8384
8385 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8386 operands[2] = force_reg (SImode, operands[2]);
8387
8388 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8389 operands[3], operands[4]));
8390 DONE;
8391 }"
8392 )
8393
8394 ;; The USE in this pattern is needed to tell flow analysis that this is
8395 ;; a CASESI insn. It has no other purpose.
8396 (define_expand "arm_casesi_internal"
8397 [(parallel [(set (pc)
8398 (if_then_else
8399 (leu (match_operand:SI 0 "s_register_operand")
8400 (match_operand:SI 1 "arm_rhs_operand"))
8401 (match_dup 4)
8402 (label_ref:SI (match_operand 3 ""))))
8403 (clobber (reg:CC CC_REGNUM))
8404 (use (label_ref:SI (match_operand 2 "")))])]
8405 "TARGET_ARM"
8406 {
8407 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8408 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8409 gen_rtx_LABEL_REF (SImode, operands[2]));
8410 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8411 MEM_READONLY_P (operands[4]) = 1;
8412 MEM_NOTRAP_P (operands[4]) = 1;
8413 })
8414
8415 (define_insn "*arm_casesi_internal"
8416 [(parallel [(set (pc)
8417 (if_then_else
8418 (leu (match_operand:SI 0 "s_register_operand" "r")
8419 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8420 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8421 (label_ref:SI (match_operand 2 "" ""))))
8422 (label_ref:SI (match_operand 3 "" ""))))
8423 (clobber (reg:CC CC_REGNUM))
8424 (use (label_ref:SI (match_dup 2)))])]
8425 "TARGET_ARM"
8426 "*
8427 if (flag_pic)
8428 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8429 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8430 "
8431 [(set_attr "conds" "clob")
8432 (set_attr "length" "12")
8433 (set_attr "type" "multiple")]
8434 )
8435
8436 (define_expand "indirect_jump"
8437 [(set (pc)
8438 (match_operand:SI 0 "s_register_operand"))]
8439 "TARGET_EITHER"
8440 "
8441 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8442 address and use bx. */
8443 if (TARGET_THUMB2)
8444 {
8445 rtx tmp;
8446 tmp = gen_reg_rtx (SImode);
8447 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8448 operands[0] = tmp;
8449 }
8450 "
8451 )
8452
8453 ;; NB Never uses BX.
8454 (define_insn "*arm_indirect_jump"
8455 [(set (pc)
8456 (match_operand:SI 0 "s_register_operand" "r"))]
8457 "TARGET_ARM"
8458 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8459 [(set_attr "predicable" "yes")
8460 (set_attr "type" "branch")]
8461 )
8462
8463 (define_insn "*load_indirect_jump"
8464 [(set (pc)
8465 (match_operand:SI 0 "memory_operand" "m"))]
8466 "TARGET_ARM"
8467 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8468 [(set_attr "type" "load_4")
8469 (set_attr "pool_range" "4096")
8470 (set_attr "neg_pool_range" "4084")
8471 (set_attr "predicable" "yes")]
8472 )
8473
8474 \f
8475 ;; Misc insns
8476
8477 (define_insn "nop"
8478 [(const_int 0)]
8479 "TARGET_EITHER"
8480 "nop"
8481 [(set (attr "length")
8482 (if_then_else (eq_attr "is_thumb" "yes")
8483 (const_int 2)
8484 (const_int 4)))
8485 (set_attr "type" "mov_reg")]
8486 )
8487
8488 (define_insn "trap"
8489 [(trap_if (const_int 1) (const_int 0))]
8490 ""
8491 "*
8492 if (TARGET_ARM)
8493 return \".inst\\t0xe7f000f0\";
8494 else
8495 return \".inst\\t0xdeff\";
8496 "
8497 [(set (attr "length")
8498 (if_then_else (eq_attr "is_thumb" "yes")
8499 (const_int 2)
8500 (const_int 4)))
8501 (set_attr "type" "trap")
8502 (set_attr "conds" "unconditional")]
8503 )
8504
8505 \f
8506 ;; Patterns to allow combination of arithmetic, cond code and shifts
8507
8508 (define_insn "*<arith_shift_insn>_multsi"
8509 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8510 (SHIFTABLE_OPS:SI
8511 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8512 (match_operand:SI 3 "power_of_two_operand" ""))
8513 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
8514 "TARGET_32BIT"
8515 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8516 [(set_attr "predicable" "yes")
8517 (set_attr "shift" "2")
8518 (set_attr "arch" "a,t2")
8519 (set_attr "type" "alu_shift_imm")])
8520
8521 (define_insn "*<arith_shift_insn>_shiftsi"
8522 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8523 (SHIFTABLE_OPS:SI
8524 (match_operator:SI 2 "shift_nomul_operator"
8525 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8526 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8527 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
8528 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
8529 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
8530 [(set_attr "predicable" "yes")
8531 (set_attr "shift" "3")
8532 (set_attr "arch" "a,t2,a")
8533 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
8534
8535 (define_split
8536 [(set (match_operand:SI 0 "s_register_operand" "")
8537 (match_operator:SI 1 "shiftable_operator"
8538 [(match_operator:SI 2 "shiftable_operator"
8539 [(match_operator:SI 3 "shift_operator"
8540 [(match_operand:SI 4 "s_register_operand" "")
8541 (match_operand:SI 5 "reg_or_int_operand" "")])
8542 (match_operand:SI 6 "s_register_operand" "")])
8543 (match_operand:SI 7 "arm_rhs_operand" "")]))
8544 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8545 "TARGET_32BIT"
8546 [(set (match_dup 8)
8547 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8548 (match_dup 6)]))
8549 (set (match_dup 0)
8550 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8551 "")
8552
8553 (define_insn "*arith_shiftsi_compare0"
8554 [(set (reg:CC_NOOV CC_REGNUM)
8555 (compare:CC_NOOV
8556 (match_operator:SI 1 "shiftable_operator"
8557 [(match_operator:SI 3 "shift_operator"
8558 [(match_operand:SI 4 "s_register_operand" "r,r")
8559 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8560 (match_operand:SI 2 "s_register_operand" "r,r")])
8561 (const_int 0)))
8562 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8563 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8564 (match_dup 2)]))]
8565 "TARGET_32BIT"
8566 "%i1s%?\\t%0, %2, %4%S3"
8567 [(set_attr "conds" "set")
8568 (set_attr "shift" "4")
8569 (set_attr "arch" "32,a")
8570 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8571
8572 (define_insn "*arith_shiftsi_compare0_scratch"
8573 [(set (reg:CC_NOOV CC_REGNUM)
8574 (compare:CC_NOOV
8575 (match_operator:SI 1 "shiftable_operator"
8576 [(match_operator:SI 3 "shift_operator"
8577 [(match_operand:SI 4 "s_register_operand" "r,r")
8578 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8579 (match_operand:SI 2 "s_register_operand" "r,r")])
8580 (const_int 0)))
8581 (clobber (match_scratch:SI 0 "=r,r"))]
8582 "TARGET_32BIT"
8583 "%i1s%?\\t%0, %2, %4%S3"
8584 [(set_attr "conds" "set")
8585 (set_attr "shift" "4")
8586 (set_attr "arch" "32,a")
8587 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8588
8589 (define_insn "*sub_shiftsi"
8590 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8591 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8592 (match_operator:SI 2 "shift_operator"
8593 [(match_operand:SI 3 "s_register_operand" "r,r")
8594 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8595 "TARGET_32BIT"
8596 "sub%?\\t%0, %1, %3%S2"
8597 [(set_attr "predicable" "yes")
8598 (set_attr "predicable_short_it" "no")
8599 (set_attr "shift" "3")
8600 (set_attr "arch" "32,a")
8601 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8602
8603 (define_insn "*sub_shiftsi_compare0"
8604 [(set (reg:CC_NOOV CC_REGNUM)
8605 (compare:CC_NOOV
8606 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8607 (match_operator:SI 2 "shift_operator"
8608 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8609 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8610 (const_int 0)))
8611 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8612 (minus:SI (match_dup 1)
8613 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8614 "TARGET_32BIT"
8615 "subs%?\\t%0, %1, %3%S2"
8616 [(set_attr "conds" "set")
8617 (set_attr "shift" "3")
8618 (set_attr "arch" "32,a,a")
8619 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8620
8621 (define_insn "*sub_shiftsi_compare0_scratch"
8622 [(set (reg:CC_NOOV CC_REGNUM)
8623 (compare:CC_NOOV
8624 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8625 (match_operator:SI 2 "shift_operator"
8626 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8627 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8628 (const_int 0)))
8629 (clobber (match_scratch:SI 0 "=r,r,r"))]
8630 "TARGET_32BIT"
8631 "subs%?\\t%0, %1, %3%S2"
8632 [(set_attr "conds" "set")
8633 (set_attr "shift" "3")
8634 (set_attr "arch" "32,a,a")
8635 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8636 \f
8637
8638 (define_insn_and_split "*and_scc"
8639 [(set (match_operand:SI 0 "s_register_operand" "=r")
8640 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8641 [(match_operand 2 "cc_register" "") (const_int 0)])
8642 (match_operand:SI 3 "s_register_operand" "r")))]
8643 "TARGET_ARM"
8644 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8645 "&& reload_completed"
8646 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8647 (cond_exec (match_dup 4) (set (match_dup 0)
8648 (and:SI (match_dup 3) (const_int 1))))]
8649 {
8650 machine_mode mode = GET_MODE (operands[2]);
8651 enum rtx_code rc = GET_CODE (operands[1]);
8652
8653 /* Note that operands[4] is the same as operands[1],
8654 but with VOIDmode as the result. */
8655 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8656 if (mode == CCFPmode || mode == CCFPEmode)
8657 rc = reverse_condition_maybe_unordered (rc);
8658 else
8659 rc = reverse_condition (rc);
8660 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8661 }
8662 [(set_attr "conds" "use")
8663 (set_attr "type" "multiple")
8664 (set_attr "length" "8")]
8665 )
8666
8667 (define_insn_and_split "*ior_scc"
8668 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8669 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8670 [(match_operand 2 "cc_register" "") (const_int 0)])
8671 (match_operand:SI 3 "s_register_operand" "0,?r")))]
8672 "TARGET_ARM"
8673 "@
8674 orr%d1\\t%0, %3, #1
8675 #"
8676 "&& reload_completed
8677 && REGNO (operands [0]) != REGNO (operands[3])"
8678 ;; && which_alternative == 1
8679 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8680 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8681 (cond_exec (match_dup 4) (set (match_dup 0)
8682 (ior:SI (match_dup 3) (const_int 1))))]
8683 {
8684 machine_mode mode = GET_MODE (operands[2]);
8685 enum rtx_code rc = GET_CODE (operands[1]);
8686
8687 /* Note that operands[4] is the same as operands[1],
8688 but with VOIDmode as the result. */
8689 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8690 if (mode == CCFPmode || mode == CCFPEmode)
8691 rc = reverse_condition_maybe_unordered (rc);
8692 else
8693 rc = reverse_condition (rc);
8694 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8695 }
8696 [(set_attr "conds" "use")
8697 (set_attr "length" "4,8")
8698 (set_attr "type" "logic_imm,multiple")]
8699 )
8700
8701 ; A series of splitters for the compare_scc pattern below. Note that
8702 ; order is important.
8703 (define_split
8704 [(set (match_operand:SI 0 "s_register_operand" "")
8705 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8706 (const_int 0)))
8707 (clobber (reg:CC CC_REGNUM))]
8708 "TARGET_32BIT && reload_completed"
8709 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8710
8711 (define_split
8712 [(set (match_operand:SI 0 "s_register_operand" "")
8713 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8714 (const_int 0)))
8715 (clobber (reg:CC CC_REGNUM))]
8716 "TARGET_32BIT && reload_completed"
8717 [(set (match_dup 0) (not:SI (match_dup 1)))
8718 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8719
8720 (define_split
8721 [(set (match_operand:SI 0 "s_register_operand" "")
8722 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8723 (const_int 0)))
8724 (clobber (reg:CC CC_REGNUM))]
8725 "arm_arch5t && TARGET_32BIT"
8726 [(set (match_dup 0) (clz:SI (match_dup 1)))
8727 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8728 )
8729
8730 (define_split
8731 [(set (match_operand:SI 0 "s_register_operand" "")
8732 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8733 (const_int 0)))
8734 (clobber (reg:CC CC_REGNUM))]
8735 "TARGET_32BIT && reload_completed"
8736 [(parallel
8737 [(set (reg:CC CC_REGNUM)
8738 (compare:CC (const_int 1) (match_dup 1)))
8739 (set (match_dup 0)
8740 (minus:SI (const_int 1) (match_dup 1)))])
8741 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
8742 (set (match_dup 0) (const_int 0)))])
8743
8744 (define_split
8745 [(set (match_operand:SI 0 "s_register_operand" "")
8746 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8747 (match_operand:SI 2 "const_int_operand" "")))
8748 (clobber (reg:CC CC_REGNUM))]
8749 "TARGET_32BIT && reload_completed"
8750 [(parallel
8751 [(set (reg:CC CC_REGNUM)
8752 (compare:CC (match_dup 1) (match_dup 2)))
8753 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8754 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8755 (set (match_dup 0) (const_int 1)))]
8756 {
8757 operands[3] = gen_int_mode (-INTVAL (operands[2]), SImode);
8758 })
8759
8760 (define_split
8761 [(set (match_operand:SI 0 "s_register_operand" "")
8762 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8763 (match_operand:SI 2 "arm_add_operand" "")))
8764 (clobber (reg:CC CC_REGNUM))]
8765 "TARGET_32BIT && reload_completed"
8766 [(parallel
8767 [(set (reg:CC_NOOV CC_REGNUM)
8768 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8769 (const_int 0)))
8770 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8771 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8772 (set (match_dup 0) (const_int 1)))])
8773
8774 (define_insn_and_split "*compare_scc"
8775 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8776 (match_operator:SI 1 "arm_comparison_operator"
8777 [(match_operand:SI 2 "s_register_operand" "r,r")
8778 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8779 (clobber (reg:CC CC_REGNUM))]
8780 "TARGET_32BIT"
8781 "#"
8782 "&& reload_completed"
8783 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8784 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8785 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8786 {
8787 rtx tmp1;
8788 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8789 operands[2], operands[3]);
8790 enum rtx_code rc = GET_CODE (operands[1]);
8791
8792 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
8793
8794 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8795 if (mode == CCFPmode || mode == CCFPEmode)
8796 rc = reverse_condition_maybe_unordered (rc);
8797 else
8798 rc = reverse_condition (rc);
8799 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8800 }
8801 [(set_attr "type" "multiple")]
8802 )
8803
8804 ;; Attempt to improve the sequence generated by the compare_scc splitters
8805 ;; not to use conditional execution.
8806
8807 ;; Rd = (eq (reg1) (const_int0)) // ARMv5
8808 ;; clz Rd, reg1
8809 ;; lsr Rd, Rd, #5
8810 (define_peephole2
8811 [(set (reg:CC CC_REGNUM)
8812 (compare:CC (match_operand:SI 1 "register_operand" "")
8813 (const_int 0)))
8814 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8815 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8816 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8817 (set (match_dup 0) (const_int 1)))]
8818 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8819 [(set (match_dup 0) (clz:SI (match_dup 1)))
8820 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8821 )
8822
8823 ;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8824 ;; negs Rd, reg1
8825 ;; adc Rd, Rd, reg1
8826 (define_peephole2
8827 [(set (reg:CC CC_REGNUM)
8828 (compare:CC (match_operand:SI 1 "register_operand" "")
8829 (const_int 0)))
8830 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8831 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8832 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8833 (set (match_dup 0) (const_int 1)))
8834 (match_scratch:SI 2 "r")]
8835 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8836 [(parallel
8837 [(set (reg:CC CC_REGNUM)
8838 (compare:CC (const_int 0) (match_dup 1)))
8839 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8840 (set (match_dup 0)
8841 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8842 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8843 )
8844
8845 ;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
8846 ;; sub Rd, Reg1, reg2
8847 ;; clz Rd, Rd
8848 ;; lsr Rd, Rd, #5
8849 (define_peephole2
8850 [(set (reg:CC CC_REGNUM)
8851 (compare:CC (match_operand:SI 1 "register_operand" "")
8852 (match_operand:SI 2 "arm_rhs_operand" "")))
8853 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8854 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8855 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8856 (set (match_dup 0) (const_int 1)))]
8857 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8858 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
8859 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8860 (set (match_dup 0) (clz:SI (match_dup 0)))
8861 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8862 )
8863
8864
8865 ;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
8866 ;; sub T1, Reg1, reg2
8867 ;; negs Rd, T1
8868 ;; adc Rd, Rd, T1
8869 (define_peephole2
8870 [(set (reg:CC CC_REGNUM)
8871 (compare:CC (match_operand:SI 1 "register_operand" "")
8872 (match_operand:SI 2 "arm_rhs_operand" "")))
8873 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8874 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8875 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8876 (set (match_dup 0) (const_int 1)))
8877 (match_scratch:SI 3 "r")]
8878 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8879 [(set (match_dup 3) (match_dup 4))
8880 (parallel
8881 [(set (reg:CC CC_REGNUM)
8882 (compare:CC (const_int 0) (match_dup 3)))
8883 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8884 (set (match_dup 0)
8885 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8886 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8887 "
8888 if (CONST_INT_P (operands[2]))
8889 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8890 else
8891 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8892 ")
8893
8894 (define_insn "*cond_move"
8895 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8896 (if_then_else:SI (match_operator 3 "equality_operator"
8897 [(match_operator 4 "arm_comparison_operator"
8898 [(match_operand 5 "cc_register" "") (const_int 0)])
8899 (const_int 0)])
8900 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8901 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8902 "TARGET_ARM"
8903 "*
8904 if (GET_CODE (operands[3]) == NE)
8905 {
8906 if (which_alternative != 1)
8907 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8908 if (which_alternative != 0)
8909 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8910 return \"\";
8911 }
8912 if (which_alternative != 0)
8913 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8914 if (which_alternative != 1)
8915 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8916 return \"\";
8917 "
8918 [(set_attr "conds" "use")
8919 (set_attr_alternative "type"
8920 [(if_then_else (match_operand 2 "const_int_operand" "")
8921 (const_string "mov_imm")
8922 (const_string "mov_reg"))
8923 (if_then_else (match_operand 1 "const_int_operand" "")
8924 (const_string "mov_imm")
8925 (const_string "mov_reg"))
8926 (const_string "multiple")])
8927 (set_attr "length" "4,4,8")]
8928 )
8929
8930 (define_insn "*cond_arith"
8931 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8932 (match_operator:SI 5 "shiftable_operator"
8933 [(match_operator:SI 4 "arm_comparison_operator"
8934 [(match_operand:SI 2 "s_register_operand" "r,r")
8935 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8936 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8937 (clobber (reg:CC CC_REGNUM))]
8938 "TARGET_ARM"
8939 "*
8940 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8941 return \"%i5\\t%0, %1, %2, lsr #31\";
8942
8943 output_asm_insn (\"cmp\\t%2, %3\", operands);
8944 if (GET_CODE (operands[5]) == AND)
8945 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8946 else if (GET_CODE (operands[5]) == MINUS)
8947 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8948 else if (which_alternative != 0)
8949 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8950 return \"%i5%d4\\t%0, %1, #1\";
8951 "
8952 [(set_attr "conds" "clob")
8953 (set_attr "length" "12")
8954 (set_attr "type" "multiple")]
8955 )
8956
8957 (define_insn "*cond_sub"
8958 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8959 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8960 (match_operator:SI 4 "arm_comparison_operator"
8961 [(match_operand:SI 2 "s_register_operand" "r,r")
8962 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8963 (clobber (reg:CC CC_REGNUM))]
8964 "TARGET_ARM"
8965 "*
8966 output_asm_insn (\"cmp\\t%2, %3\", operands);
8967 if (which_alternative != 0)
8968 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8969 return \"sub%d4\\t%0, %1, #1\";
8970 "
8971 [(set_attr "conds" "clob")
8972 (set_attr "length" "8,12")
8973 (set_attr "type" "multiple")]
8974 )
8975
8976 (define_insn "*cmp_ite0"
8977 [(set (match_operand 6 "dominant_cc_register" "")
8978 (compare
8979 (if_then_else:SI
8980 (match_operator 4 "arm_comparison_operator"
8981 [(match_operand:SI 0 "s_register_operand"
8982 "l,l,l,r,r,r,r,r,r")
8983 (match_operand:SI 1 "arm_add_operand"
8984 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8985 (match_operator:SI 5 "arm_comparison_operator"
8986 [(match_operand:SI 2 "s_register_operand"
8987 "l,r,r,l,l,r,r,r,r")
8988 (match_operand:SI 3 "arm_add_operand"
8989 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
8990 (const_int 0))
8991 (const_int 0)))]
8992 "TARGET_32BIT"
8993 "*
8994 {
8995 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8996 {
8997 {\"cmp%d5\\t%0, %1\",
8998 \"cmp%d4\\t%2, %3\"},
8999 {\"cmn%d5\\t%0, #%n1\",
9000 \"cmp%d4\\t%2, %3\"},
9001 {\"cmp%d5\\t%0, %1\",
9002 \"cmn%d4\\t%2, #%n3\"},
9003 {\"cmn%d5\\t%0, #%n1\",
9004 \"cmn%d4\\t%2, #%n3\"}
9005 };
9006 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9007 {
9008 {\"cmp\\t%2, %3\",
9009 \"cmp\\t%0, %1\"},
9010 {\"cmp\\t%2, %3\",
9011 \"cmn\\t%0, #%n1\"},
9012 {\"cmn\\t%2, #%n3\",
9013 \"cmp\\t%0, %1\"},
9014 {\"cmn\\t%2, #%n3\",
9015 \"cmn\\t%0, #%n1\"}
9016 };
9017 static const char * const ite[2] =
9018 {
9019 \"it\\t%d5\",
9020 \"it\\t%d4\"
9021 };
9022 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9023 CMP_CMP, CMN_CMP, CMP_CMP,
9024 CMN_CMP, CMP_CMN, CMN_CMN};
9025 int swap =
9026 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9027
9028 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9029 if (TARGET_THUMB2) {
9030 output_asm_insn (ite[swap], operands);
9031 }
9032 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9033 return \"\";
9034 }"
9035 [(set_attr "conds" "set")
9036 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9037 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9038 (set_attr "type" "multiple")
9039 (set_attr_alternative "length"
9040 [(const_int 6)
9041 (const_int 8)
9042 (const_int 8)
9043 (const_int 8)
9044 (const_int 8)
9045 (if_then_else (eq_attr "is_thumb" "no")
9046 (const_int 8)
9047 (const_int 10))
9048 (if_then_else (eq_attr "is_thumb" "no")
9049 (const_int 8)
9050 (const_int 10))
9051 (if_then_else (eq_attr "is_thumb" "no")
9052 (const_int 8)
9053 (const_int 10))
9054 (if_then_else (eq_attr "is_thumb" "no")
9055 (const_int 8)
9056 (const_int 10))])]
9057 )
9058
9059 (define_insn "*cmp_ite1"
9060 [(set (match_operand 6 "dominant_cc_register" "")
9061 (compare
9062 (if_then_else:SI
9063 (match_operator 4 "arm_comparison_operator"
9064 [(match_operand:SI 0 "s_register_operand"
9065 "l,l,l,r,r,r,r,r,r")
9066 (match_operand:SI 1 "arm_add_operand"
9067 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9068 (match_operator:SI 5 "arm_comparison_operator"
9069 [(match_operand:SI 2 "s_register_operand"
9070 "l,r,r,l,l,r,r,r,r")
9071 (match_operand:SI 3 "arm_add_operand"
9072 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9073 (const_int 1))
9074 (const_int 0)))]
9075 "TARGET_32BIT"
9076 "*
9077 {
9078 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9079 {
9080 {\"cmp\\t%0, %1\",
9081 \"cmp\\t%2, %3\"},
9082 {\"cmn\\t%0, #%n1\",
9083 \"cmp\\t%2, %3\"},
9084 {\"cmp\\t%0, %1\",
9085 \"cmn\\t%2, #%n3\"},
9086 {\"cmn\\t%0, #%n1\",
9087 \"cmn\\t%2, #%n3\"}
9088 };
9089 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9090 {
9091 {\"cmp%d4\\t%2, %3\",
9092 \"cmp%D5\\t%0, %1\"},
9093 {\"cmp%d4\\t%2, %3\",
9094 \"cmn%D5\\t%0, #%n1\"},
9095 {\"cmn%d4\\t%2, #%n3\",
9096 \"cmp%D5\\t%0, %1\"},
9097 {\"cmn%d4\\t%2, #%n3\",
9098 \"cmn%D5\\t%0, #%n1\"}
9099 };
9100 static const char * const ite[2] =
9101 {
9102 \"it\\t%d4\",
9103 \"it\\t%D5\"
9104 };
9105 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9106 CMP_CMP, CMN_CMP, CMP_CMP,
9107 CMN_CMP, CMP_CMN, CMN_CMN};
9108 int swap =
9109 comparison_dominates_p (GET_CODE (operands[5]),
9110 reverse_condition (GET_CODE (operands[4])));
9111
9112 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9113 if (TARGET_THUMB2) {
9114 output_asm_insn (ite[swap], operands);
9115 }
9116 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9117 return \"\";
9118 }"
9119 [(set_attr "conds" "set")
9120 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9121 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9122 (set_attr_alternative "length"
9123 [(const_int 6)
9124 (const_int 8)
9125 (const_int 8)
9126 (const_int 8)
9127 (const_int 8)
9128 (if_then_else (eq_attr "is_thumb" "no")
9129 (const_int 8)
9130 (const_int 10))
9131 (if_then_else (eq_attr "is_thumb" "no")
9132 (const_int 8)
9133 (const_int 10))
9134 (if_then_else (eq_attr "is_thumb" "no")
9135 (const_int 8)
9136 (const_int 10))
9137 (if_then_else (eq_attr "is_thumb" "no")
9138 (const_int 8)
9139 (const_int 10))])
9140 (set_attr "type" "multiple")]
9141 )
9142
9143 (define_insn "*cmp_and"
9144 [(set (match_operand 6 "dominant_cc_register" "")
9145 (compare
9146 (and:SI
9147 (match_operator 4 "arm_comparison_operator"
9148 [(match_operand:SI 0 "s_register_operand"
9149 "l,l,l,r,r,r,r,r,r,r")
9150 (match_operand:SI 1 "arm_add_operand"
9151 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
9152 (match_operator:SI 5 "arm_comparison_operator"
9153 [(match_operand:SI 2 "s_register_operand"
9154 "l,r,r,l,l,r,r,r,r,r")
9155 (match_operand:SI 3 "arm_add_operand"
9156 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
9157 (const_int 0)))]
9158 "TARGET_32BIT"
9159 "*
9160 {
9161 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9162 {
9163 {\"cmp%d5\\t%0, %1\",
9164 \"cmp%d4\\t%2, %3\"},
9165 {\"cmn%d5\\t%0, #%n1\",
9166 \"cmp%d4\\t%2, %3\"},
9167 {\"cmp%d5\\t%0, %1\",
9168 \"cmn%d4\\t%2, #%n3\"},
9169 {\"cmn%d5\\t%0, #%n1\",
9170 \"cmn%d4\\t%2, #%n3\"}
9171 };
9172 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9173 {
9174 {\"cmp\\t%2, %3\",
9175 \"cmp\\t%0, %1\"},
9176 {\"cmp\\t%2, %3\",
9177 \"cmn\\t%0, #%n1\"},
9178 {\"cmn\\t%2, #%n3\",
9179 \"cmp\\t%0, %1\"},
9180 {\"cmn\\t%2, #%n3\",
9181 \"cmn\\t%0, #%n1\"}
9182 };
9183 static const char *const ite[2] =
9184 {
9185 \"it\\t%d5\",
9186 \"it\\t%d4\"
9187 };
9188 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9189 CMP_CMP, CMN_CMP, CMP_CMP,
9190 CMP_CMP, CMN_CMP, CMP_CMN,
9191 CMN_CMN};
9192 int swap =
9193 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9194
9195 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9196 if (TARGET_THUMB2) {
9197 output_asm_insn (ite[swap], operands);
9198 }
9199 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9200 return \"\";
9201 }"
9202 [(set_attr "conds" "set")
9203 (set_attr "predicable" "no")
9204 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9205 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
9206 (set_attr_alternative "length"
9207 [(const_int 6)
9208 (const_int 8)
9209 (const_int 8)
9210 (const_int 8)
9211 (const_int 8)
9212 (const_int 6)
9213 (if_then_else (eq_attr "is_thumb" "no")
9214 (const_int 8)
9215 (const_int 10))
9216 (if_then_else (eq_attr "is_thumb" "no")
9217 (const_int 8)
9218 (const_int 10))
9219 (if_then_else (eq_attr "is_thumb" "no")
9220 (const_int 8)
9221 (const_int 10))
9222 (if_then_else (eq_attr "is_thumb" "no")
9223 (const_int 8)
9224 (const_int 10))])
9225 (set_attr "type" "multiple")]
9226 )
9227
9228 (define_insn "*cmp_ior"
9229 [(set (match_operand 6 "dominant_cc_register" "")
9230 (compare
9231 (ior:SI
9232 (match_operator 4 "arm_comparison_operator"
9233 [(match_operand:SI 0 "s_register_operand"
9234 "l,l,l,r,r,r,r,r,r,r")
9235 (match_operand:SI 1 "arm_add_operand"
9236 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
9237 (match_operator:SI 5 "arm_comparison_operator"
9238 [(match_operand:SI 2 "s_register_operand"
9239 "l,r,r,l,l,r,r,r,r,r")
9240 (match_operand:SI 3 "arm_add_operand"
9241 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
9242 (const_int 0)))]
9243 "TARGET_32BIT"
9244 "*
9245 {
9246 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9247 {
9248 {\"cmp\\t%0, %1\",
9249 \"cmp\\t%2, %3\"},
9250 {\"cmn\\t%0, #%n1\",
9251 \"cmp\\t%2, %3\"},
9252 {\"cmp\\t%0, %1\",
9253 \"cmn\\t%2, #%n3\"},
9254 {\"cmn\\t%0, #%n1\",
9255 \"cmn\\t%2, #%n3\"}
9256 };
9257 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9258 {
9259 {\"cmp%D4\\t%2, %3\",
9260 \"cmp%D5\\t%0, %1\"},
9261 {\"cmp%D4\\t%2, %3\",
9262 \"cmn%D5\\t%0, #%n1\"},
9263 {\"cmn%D4\\t%2, #%n3\",
9264 \"cmp%D5\\t%0, %1\"},
9265 {\"cmn%D4\\t%2, #%n3\",
9266 \"cmn%D5\\t%0, #%n1\"}
9267 };
9268 static const char *const ite[2] =
9269 {
9270 \"it\\t%D4\",
9271 \"it\\t%D5\"
9272 };
9273 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9274 CMP_CMP, CMN_CMP, CMP_CMP,
9275 CMP_CMP, CMN_CMP, CMP_CMN,
9276 CMN_CMN};
9277 int swap =
9278 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9279
9280 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9281 if (TARGET_THUMB2) {
9282 output_asm_insn (ite[swap], operands);
9283 }
9284 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9285 return \"\";
9286 }
9287 "
9288 [(set_attr "conds" "set")
9289 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9290 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
9291 (set_attr_alternative "length"
9292 [(const_int 6)
9293 (const_int 8)
9294 (const_int 8)
9295 (const_int 8)
9296 (const_int 8)
9297 (const_int 6)
9298 (if_then_else (eq_attr "is_thumb" "no")
9299 (const_int 8)
9300 (const_int 10))
9301 (if_then_else (eq_attr "is_thumb" "no")
9302 (const_int 8)
9303 (const_int 10))
9304 (if_then_else (eq_attr "is_thumb" "no")
9305 (const_int 8)
9306 (const_int 10))
9307 (if_then_else (eq_attr "is_thumb" "no")
9308 (const_int 8)
9309 (const_int 10))])
9310 (set_attr "type" "multiple")]
9311 )
9312
9313 (define_insn_and_split "*ior_scc_scc"
9314 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9315 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9316 [(match_operand:SI 1 "s_register_operand" "l,r")
9317 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9318 (match_operator:SI 6 "arm_comparison_operator"
9319 [(match_operand:SI 4 "s_register_operand" "l,r")
9320 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9321 (clobber (reg:CC CC_REGNUM))]
9322 "TARGET_32BIT
9323 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9324 != CCmode)"
9325 "#"
9326 "TARGET_32BIT && reload_completed"
9327 [(set (match_dup 7)
9328 (compare
9329 (ior:SI
9330 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9331 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9332 (const_int 0)))
9333 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9334 "operands[7]
9335 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9336 DOM_CC_X_OR_Y),
9337 CC_REGNUM);"
9338 [(set_attr "conds" "clob")
9339 (set_attr "enabled_for_short_it" "yes,no")
9340 (set_attr "length" "16")
9341 (set_attr "type" "multiple")]
9342 )
9343
9344 ; If the above pattern is followed by a CMP insn, then the compare is
9345 ; redundant, since we can rework the conditional instruction that follows.
9346 (define_insn_and_split "*ior_scc_scc_cmp"
9347 [(set (match_operand 0 "dominant_cc_register" "")
9348 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9349 [(match_operand:SI 1 "s_register_operand" "l,r")
9350 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9351 (match_operator:SI 6 "arm_comparison_operator"
9352 [(match_operand:SI 4 "s_register_operand" "l,r")
9353 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9354 (const_int 0)))
9355 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9356 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9357 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9358 "TARGET_32BIT"
9359 "#"
9360 "TARGET_32BIT && reload_completed"
9361 [(set (match_dup 0)
9362 (compare
9363 (ior:SI
9364 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9365 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9366 (const_int 0)))
9367 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9368 ""
9369 [(set_attr "conds" "set")
9370 (set_attr "enabled_for_short_it" "yes,no")
9371 (set_attr "length" "16")
9372 (set_attr "type" "multiple")]
9373 )
9374
9375 (define_insn_and_split "*and_scc_scc"
9376 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9377 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9378 [(match_operand:SI 1 "s_register_operand" "l,r")
9379 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9380 (match_operator:SI 6 "arm_comparison_operator"
9381 [(match_operand:SI 4 "s_register_operand" "l,r")
9382 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9383 (clobber (reg:CC CC_REGNUM))]
9384 "TARGET_32BIT
9385 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9386 != CCmode)"
9387 "#"
9388 "TARGET_32BIT && reload_completed
9389 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9390 != CCmode)"
9391 [(set (match_dup 7)
9392 (compare
9393 (and:SI
9394 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9395 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9396 (const_int 0)))
9397 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9398 "operands[7]
9399 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9400 DOM_CC_X_AND_Y),
9401 CC_REGNUM);"
9402 [(set_attr "conds" "clob")
9403 (set_attr "enabled_for_short_it" "yes,no")
9404 (set_attr "length" "16")
9405 (set_attr "type" "multiple")]
9406 )
9407
9408 ; If the above pattern is followed by a CMP insn, then the compare is
9409 ; redundant, since we can rework the conditional instruction that follows.
9410 (define_insn_and_split "*and_scc_scc_cmp"
9411 [(set (match_operand 0 "dominant_cc_register" "")
9412 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9413 [(match_operand:SI 1 "s_register_operand" "l,r")
9414 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9415 (match_operator:SI 6 "arm_comparison_operator"
9416 [(match_operand:SI 4 "s_register_operand" "l,r")
9417 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9418 (const_int 0)))
9419 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9420 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9421 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9422 "TARGET_32BIT"
9423 "#"
9424 "TARGET_32BIT && reload_completed"
9425 [(set (match_dup 0)
9426 (compare
9427 (and:SI
9428 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9429 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9430 (const_int 0)))
9431 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9432 ""
9433 [(set_attr "conds" "set")
9434 (set_attr "enabled_for_short_it" "yes,no")
9435 (set_attr "length" "16")
9436 (set_attr "type" "multiple")]
9437 )
9438
9439 ;; If there is no dominance in the comparison, then we can still save an
9440 ;; instruction in the AND case, since we can know that the second compare
9441 ;; need only zero the value if false (if true, then the value is already
9442 ;; correct).
9443 (define_insn_and_split "*and_scc_scc_nodom"
9444 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
9445 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9446 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9447 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9448 (match_operator:SI 6 "arm_comparison_operator"
9449 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9450 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9451 (clobber (reg:CC CC_REGNUM))]
9452 "TARGET_32BIT
9453 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9454 == CCmode)"
9455 "#"
9456 "TARGET_32BIT && reload_completed"
9457 [(parallel [(set (match_dup 0)
9458 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9459 (clobber (reg:CC CC_REGNUM))])
9460 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9461 (set (match_dup 0)
9462 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9463 (match_dup 0)
9464 (const_int 0)))]
9465 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9466 operands[4], operands[5]),
9467 CC_REGNUM);
9468 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9469 operands[5]);"
9470 [(set_attr "conds" "clob")
9471 (set_attr "length" "20")
9472 (set_attr "type" "multiple")]
9473 )
9474
9475 (define_split
9476 [(set (reg:CC_NOOV CC_REGNUM)
9477 (compare:CC_NOOV (ior:SI
9478 (and:SI (match_operand:SI 0 "s_register_operand" "")
9479 (const_int 1))
9480 (match_operator:SI 1 "arm_comparison_operator"
9481 [(match_operand:SI 2 "s_register_operand" "")
9482 (match_operand:SI 3 "arm_add_operand" "")]))
9483 (const_int 0)))
9484 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9485 "TARGET_ARM"
9486 [(set (match_dup 4)
9487 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9488 (match_dup 0)))
9489 (set (reg:CC_NOOV CC_REGNUM)
9490 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9491 (const_int 0)))]
9492 "")
9493
9494 (define_split
9495 [(set (reg:CC_NOOV CC_REGNUM)
9496 (compare:CC_NOOV (ior:SI
9497 (match_operator:SI 1 "arm_comparison_operator"
9498 [(match_operand:SI 2 "s_register_operand" "")
9499 (match_operand:SI 3 "arm_add_operand" "")])
9500 (and:SI (match_operand:SI 0 "s_register_operand" "")
9501 (const_int 1)))
9502 (const_int 0)))
9503 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9504 "TARGET_ARM"
9505 [(set (match_dup 4)
9506 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9507 (match_dup 0)))
9508 (set (reg:CC_NOOV CC_REGNUM)
9509 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9510 (const_int 0)))]
9511 "")
9512 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9513
9514 (define_insn_and_split "*negscc"
9515 [(set (match_operand:SI 0 "s_register_operand" "=r")
9516 (neg:SI (match_operator 3 "arm_comparison_operator"
9517 [(match_operand:SI 1 "s_register_operand" "r")
9518 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9519 (clobber (reg:CC CC_REGNUM))]
9520 "TARGET_ARM"
9521 "#"
9522 "&& reload_completed"
9523 [(const_int 0)]
9524 {
9525 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
9526
9527 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9528 {
9529 /* Emit mov\\t%0, %1, asr #31 */
9530 emit_insn (gen_rtx_SET (operands[0],
9531 gen_rtx_ASHIFTRT (SImode,
9532 operands[1],
9533 GEN_INT (31))));
9534 DONE;
9535 }
9536 else if (GET_CODE (operands[3]) == NE)
9537 {
9538 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9539 if (CONST_INT_P (operands[2]))
9540 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9541 gen_int_mode (-INTVAL (operands[2]),
9542 SImode)));
9543 else
9544 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9545
9546 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9547 gen_rtx_NE (SImode,
9548 cc_reg,
9549 const0_rtx),
9550 gen_rtx_SET (operands[0],
9551 GEN_INT (~0))));
9552 DONE;
9553 }
9554 else
9555 {
9556 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9557 emit_insn (gen_rtx_SET (cc_reg,
9558 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9559 enum rtx_code rc = GET_CODE (operands[3]);
9560
9561 rc = reverse_condition (rc);
9562 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9563 gen_rtx_fmt_ee (rc,
9564 VOIDmode,
9565 cc_reg,
9566 const0_rtx),
9567 gen_rtx_SET (operands[0], const0_rtx)));
9568 rc = GET_CODE (operands[3]);
9569 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9570 gen_rtx_fmt_ee (rc,
9571 VOIDmode,
9572 cc_reg,
9573 const0_rtx),
9574 gen_rtx_SET (operands[0],
9575 GEN_INT (~0))));
9576 DONE;
9577 }
9578 FAIL;
9579 }
9580 [(set_attr "conds" "clob")
9581 (set_attr "length" "12")
9582 (set_attr "type" "multiple")]
9583 )
9584
9585 (define_insn_and_split "movcond_addsi"
9586 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9587 (if_then_else:SI
9588 (match_operator 5 "comparison_operator"
9589 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9590 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9591 (const_int 0)])
9592 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9593 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9594 (clobber (reg:CC CC_REGNUM))]
9595 "TARGET_32BIT"
9596 "#"
9597 "&& reload_completed"
9598 [(set (reg:CC_NOOV CC_REGNUM)
9599 (compare:CC_NOOV
9600 (plus:SI (match_dup 3)
9601 (match_dup 4))
9602 (const_int 0)))
9603 (set (match_dup 0) (match_dup 1))
9604 (cond_exec (match_dup 6)
9605 (set (match_dup 0) (match_dup 2)))]
9606 "
9607 {
9608 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
9609 operands[3], operands[4]);
9610 enum rtx_code rc = GET_CODE (operands[5]);
9611 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9612 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
9613 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
9614 rc = reverse_condition (rc);
9615 else
9616 std::swap (operands[1], operands[2]);
9617
9618 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9619 }
9620 "
9621 [(set_attr "conds" "clob")
9622 (set_attr "enabled_for_short_it" "no,yes,yes")
9623 (set_attr "type" "multiple")]
9624 )
9625
9626 (define_insn "movcond"
9627 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9628 (if_then_else:SI
9629 (match_operator 5 "arm_comparison_operator"
9630 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9631 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9632 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9633 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9634 (clobber (reg:CC CC_REGNUM))]
9635 "TARGET_ARM"
9636 "*
9637 if (GET_CODE (operands[5]) == LT
9638 && (operands[4] == const0_rtx))
9639 {
9640 if (which_alternative != 1 && REG_P (operands[1]))
9641 {
9642 if (operands[2] == const0_rtx)
9643 return \"and\\t%0, %1, %3, asr #31\";
9644 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9645 }
9646 else if (which_alternative != 0 && REG_P (operands[2]))
9647 {
9648 if (operands[1] == const0_rtx)
9649 return \"bic\\t%0, %2, %3, asr #31\";
9650 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9651 }
9652 /* The only case that falls through to here is when both ops 1 & 2
9653 are constants. */
9654 }
9655
9656 if (GET_CODE (operands[5]) == GE
9657 && (operands[4] == const0_rtx))
9658 {
9659 if (which_alternative != 1 && REG_P (operands[1]))
9660 {
9661 if (operands[2] == const0_rtx)
9662 return \"bic\\t%0, %1, %3, asr #31\";
9663 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9664 }
9665 else if (which_alternative != 0 && REG_P (operands[2]))
9666 {
9667 if (operands[1] == const0_rtx)
9668 return \"and\\t%0, %2, %3, asr #31\";
9669 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9670 }
9671 /* The only case that falls through to here is when both ops 1 & 2
9672 are constants. */
9673 }
9674 if (CONST_INT_P (operands[4])
9675 && !const_ok_for_arm (INTVAL (operands[4])))
9676 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9677 else
9678 output_asm_insn (\"cmp\\t%3, %4\", operands);
9679 if (which_alternative != 0)
9680 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9681 if (which_alternative != 1)
9682 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9683 return \"\";
9684 "
9685 [(set_attr "conds" "clob")
9686 (set_attr "length" "8,8,12")
9687 (set_attr "type" "multiple")]
9688 )
9689
9690 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9691
9692 (define_insn "*ifcompare_plus_move"
9693 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9694 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9695 [(match_operand:SI 4 "s_register_operand" "r,r")
9696 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9697 (plus:SI
9698 (match_operand:SI 2 "s_register_operand" "r,r")
9699 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9700 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9701 (clobber (reg:CC CC_REGNUM))]
9702 "TARGET_ARM"
9703 "#"
9704 [(set_attr "conds" "clob")
9705 (set_attr "length" "8,12")
9706 (set_attr "type" "multiple")]
9707 )
9708
9709 (define_insn "*if_plus_move"
9710 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9711 (if_then_else:SI
9712 (match_operator 4 "arm_comparison_operator"
9713 [(match_operand 5 "cc_register" "") (const_int 0)])
9714 (plus:SI
9715 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9716 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9717 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9718 "TARGET_ARM"
9719 "@
9720 add%d4\\t%0, %2, %3
9721 sub%d4\\t%0, %2, #%n3
9722 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9723 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9724 [(set_attr "conds" "use")
9725 (set_attr "length" "4,4,8,8")
9726 (set_attr_alternative "type"
9727 [(if_then_else (match_operand 3 "const_int_operand" "")
9728 (const_string "alu_imm" )
9729 (const_string "alu_sreg"))
9730 (const_string "alu_imm")
9731 (const_string "multiple")
9732 (const_string "multiple")])]
9733 )
9734
9735 (define_insn "*ifcompare_move_plus"
9736 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9737 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9738 [(match_operand:SI 4 "s_register_operand" "r,r")
9739 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9740 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9741 (plus:SI
9742 (match_operand:SI 2 "s_register_operand" "r,r")
9743 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9744 (clobber (reg:CC CC_REGNUM))]
9745 "TARGET_ARM"
9746 "#"
9747 [(set_attr "conds" "clob")
9748 (set_attr "length" "8,12")
9749 (set_attr "type" "multiple")]
9750 )
9751
9752 (define_insn "*if_move_plus"
9753 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9754 (if_then_else:SI
9755 (match_operator 4 "arm_comparison_operator"
9756 [(match_operand 5 "cc_register" "") (const_int 0)])
9757 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9758 (plus:SI
9759 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9760 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9761 "TARGET_ARM"
9762 "@
9763 add%D4\\t%0, %2, %3
9764 sub%D4\\t%0, %2, #%n3
9765 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9766 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9767 [(set_attr "conds" "use")
9768 (set_attr "length" "4,4,8,8")
9769 (set_attr_alternative "type"
9770 [(if_then_else (match_operand 3 "const_int_operand" "")
9771 (const_string "alu_imm" )
9772 (const_string "alu_sreg"))
9773 (const_string "alu_imm")
9774 (const_string "multiple")
9775 (const_string "multiple")])]
9776 )
9777
9778 (define_insn "*ifcompare_arith_arith"
9779 [(set (match_operand:SI 0 "s_register_operand" "=r")
9780 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9781 [(match_operand:SI 5 "s_register_operand" "r")
9782 (match_operand:SI 6 "arm_add_operand" "rIL")])
9783 (match_operator:SI 8 "shiftable_operator"
9784 [(match_operand:SI 1 "s_register_operand" "r")
9785 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9786 (match_operator:SI 7 "shiftable_operator"
9787 [(match_operand:SI 3 "s_register_operand" "r")
9788 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9789 (clobber (reg:CC CC_REGNUM))]
9790 "TARGET_ARM"
9791 "#"
9792 [(set_attr "conds" "clob")
9793 (set_attr "length" "12")
9794 (set_attr "type" "multiple")]
9795 )
9796
9797 (define_insn "*if_arith_arith"
9798 [(set (match_operand:SI 0 "s_register_operand" "=r")
9799 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9800 [(match_operand 8 "cc_register" "") (const_int 0)])
9801 (match_operator:SI 6 "shiftable_operator"
9802 [(match_operand:SI 1 "s_register_operand" "r")
9803 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9804 (match_operator:SI 7 "shiftable_operator"
9805 [(match_operand:SI 3 "s_register_operand" "r")
9806 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9807 "TARGET_ARM"
9808 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9809 [(set_attr "conds" "use")
9810 (set_attr "length" "8")
9811 (set_attr "type" "multiple")]
9812 )
9813
9814 (define_insn "*ifcompare_arith_move"
9815 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9816 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9817 [(match_operand:SI 2 "s_register_operand" "r,r")
9818 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9819 (match_operator:SI 7 "shiftable_operator"
9820 [(match_operand:SI 4 "s_register_operand" "r,r")
9821 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9822 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9823 (clobber (reg:CC CC_REGNUM))]
9824 "TARGET_ARM"
9825 "*
9826 /* If we have an operation where (op x 0) is the identity operation and
9827 the conditional operator is LT or GE and we are comparing against zero and
9828 everything is in registers then we can do this in two instructions. */
9829 if (operands[3] == const0_rtx
9830 && GET_CODE (operands[7]) != AND
9831 && REG_P (operands[5])
9832 && REG_P (operands[1])
9833 && REGNO (operands[1]) == REGNO (operands[4])
9834 && REGNO (operands[4]) != REGNO (operands[0]))
9835 {
9836 if (GET_CODE (operands[6]) == LT)
9837 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9838 else if (GET_CODE (operands[6]) == GE)
9839 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9840 }
9841 if (CONST_INT_P (operands[3])
9842 && !const_ok_for_arm (INTVAL (operands[3])))
9843 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9844 else
9845 output_asm_insn (\"cmp\\t%2, %3\", operands);
9846 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9847 if (which_alternative != 0)
9848 return \"mov%D6\\t%0, %1\";
9849 return \"\";
9850 "
9851 [(set_attr "conds" "clob")
9852 (set_attr "length" "8,12")
9853 (set_attr "type" "multiple")]
9854 )
9855
9856 (define_insn "*if_arith_move"
9857 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9858 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9859 [(match_operand 6 "cc_register" "") (const_int 0)])
9860 (match_operator:SI 5 "shiftable_operator"
9861 [(match_operand:SI 2 "s_register_operand" "r,r")
9862 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9863 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9864 "TARGET_ARM"
9865 "@
9866 %I5%d4\\t%0, %2, %3
9867 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9868 [(set_attr "conds" "use")
9869 (set_attr "length" "4,8")
9870 (set_attr_alternative "type"
9871 [(if_then_else (match_operand 3 "const_int_operand" "")
9872 (const_string "alu_shift_imm" )
9873 (const_string "alu_shift_reg"))
9874 (const_string "multiple")])]
9875 )
9876
9877 (define_insn "*ifcompare_move_arith"
9878 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9879 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9880 [(match_operand:SI 4 "s_register_operand" "r,r")
9881 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9882 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9883 (match_operator:SI 7 "shiftable_operator"
9884 [(match_operand:SI 2 "s_register_operand" "r,r")
9885 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9886 (clobber (reg:CC CC_REGNUM))]
9887 "TARGET_ARM"
9888 "*
9889 /* If we have an operation where (op x 0) is the identity operation and
9890 the conditional operator is LT or GE and we are comparing against zero and
9891 everything is in registers then we can do this in two instructions */
9892 if (operands[5] == const0_rtx
9893 && GET_CODE (operands[7]) != AND
9894 && REG_P (operands[3])
9895 && REG_P (operands[1])
9896 && REGNO (operands[1]) == REGNO (operands[2])
9897 && REGNO (operands[2]) != REGNO (operands[0]))
9898 {
9899 if (GET_CODE (operands[6]) == GE)
9900 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9901 else if (GET_CODE (operands[6]) == LT)
9902 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9903 }
9904
9905 if (CONST_INT_P (operands[5])
9906 && !const_ok_for_arm (INTVAL (operands[5])))
9907 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9908 else
9909 output_asm_insn (\"cmp\\t%4, %5\", operands);
9910
9911 if (which_alternative != 0)
9912 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9913 return \"%I7%D6\\t%0, %2, %3\";
9914 "
9915 [(set_attr "conds" "clob")
9916 (set_attr "length" "8,12")
9917 (set_attr "type" "multiple")]
9918 )
9919
9920 (define_insn "*if_move_arith"
9921 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9922 (if_then_else:SI
9923 (match_operator 4 "arm_comparison_operator"
9924 [(match_operand 6 "cc_register" "") (const_int 0)])
9925 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9926 (match_operator:SI 5 "shiftable_operator"
9927 [(match_operand:SI 2 "s_register_operand" "r,r")
9928 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9929 "TARGET_ARM"
9930 "@
9931 %I5%D4\\t%0, %2, %3
9932 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9933 [(set_attr "conds" "use")
9934 (set_attr "length" "4,8")
9935 (set_attr_alternative "type"
9936 [(if_then_else (match_operand 3 "const_int_operand" "")
9937 (const_string "alu_shift_imm" )
9938 (const_string "alu_shift_reg"))
9939 (const_string "multiple")])]
9940 )
9941
9942 (define_insn "*ifcompare_move_not"
9943 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9944 (if_then_else:SI
9945 (match_operator 5 "arm_comparison_operator"
9946 [(match_operand:SI 3 "s_register_operand" "r,r")
9947 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9948 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9949 (not:SI
9950 (match_operand:SI 2 "s_register_operand" "r,r"))))
9951 (clobber (reg:CC CC_REGNUM))]
9952 "TARGET_ARM"
9953 "#"
9954 [(set_attr "conds" "clob")
9955 (set_attr "length" "8,12")
9956 (set_attr "type" "multiple")]
9957 )
9958
9959 (define_insn "*if_move_not"
9960 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9961 (if_then_else:SI
9962 (match_operator 4 "arm_comparison_operator"
9963 [(match_operand 3 "cc_register" "") (const_int 0)])
9964 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9965 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9966 "TARGET_ARM"
9967 "@
9968 mvn%D4\\t%0, %2
9969 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9970 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9971 [(set_attr "conds" "use")
9972 (set_attr "type" "mvn_reg")
9973 (set_attr "length" "4,8,8")
9974 (set_attr "type" "mvn_reg,multiple,multiple")]
9975 )
9976
9977 (define_insn "*ifcompare_not_move"
9978 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9979 (if_then_else:SI
9980 (match_operator 5 "arm_comparison_operator"
9981 [(match_operand:SI 3 "s_register_operand" "r,r")
9982 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9983 (not:SI
9984 (match_operand:SI 2 "s_register_operand" "r,r"))
9985 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9986 (clobber (reg:CC CC_REGNUM))]
9987 "TARGET_ARM"
9988 "#"
9989 [(set_attr "conds" "clob")
9990 (set_attr "length" "8,12")
9991 (set_attr "type" "multiple")]
9992 )
9993
9994 (define_insn "*if_not_move"
9995 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9996 (if_then_else:SI
9997 (match_operator 4 "arm_comparison_operator"
9998 [(match_operand 3 "cc_register" "") (const_int 0)])
9999 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10000 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10001 "TARGET_ARM"
10002 "@
10003 mvn%d4\\t%0, %2
10004 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10005 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10006 [(set_attr "conds" "use")
10007 (set_attr "type" "mvn_reg,multiple,multiple")
10008 (set_attr "length" "4,8,8")]
10009 )
10010
10011 (define_insn "*ifcompare_shift_move"
10012 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10013 (if_then_else:SI
10014 (match_operator 6 "arm_comparison_operator"
10015 [(match_operand:SI 4 "s_register_operand" "r,r")
10016 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10017 (match_operator:SI 7 "shift_operator"
10018 [(match_operand:SI 2 "s_register_operand" "r,r")
10019 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10020 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10021 (clobber (reg:CC CC_REGNUM))]
10022 "TARGET_ARM"
10023 "#"
10024 [(set_attr "conds" "clob")
10025 (set_attr "length" "8,12")
10026 (set_attr "type" "multiple")]
10027 )
10028
10029 (define_insn "*if_shift_move"
10030 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10031 (if_then_else:SI
10032 (match_operator 5 "arm_comparison_operator"
10033 [(match_operand 6 "cc_register" "") (const_int 0)])
10034 (match_operator:SI 4 "shift_operator"
10035 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10036 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10037 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10038 "TARGET_ARM"
10039 "@
10040 mov%d5\\t%0, %2%S4
10041 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10042 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10043 [(set_attr "conds" "use")
10044 (set_attr "shift" "2")
10045 (set_attr "length" "4,8,8")
10046 (set_attr_alternative "type"
10047 [(if_then_else (match_operand 3 "const_int_operand" "")
10048 (const_string "mov_shift" )
10049 (const_string "mov_shift_reg"))
10050 (const_string "multiple")
10051 (const_string "multiple")])]
10052 )
10053
10054 (define_insn "*ifcompare_move_shift"
10055 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10056 (if_then_else:SI
10057 (match_operator 6 "arm_comparison_operator"
10058 [(match_operand:SI 4 "s_register_operand" "r,r")
10059 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10060 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10061 (match_operator:SI 7 "shift_operator"
10062 [(match_operand:SI 2 "s_register_operand" "r,r")
10063 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10064 (clobber (reg:CC CC_REGNUM))]
10065 "TARGET_ARM"
10066 "#"
10067 [(set_attr "conds" "clob")
10068 (set_attr "length" "8,12")
10069 (set_attr "type" "multiple")]
10070 )
10071
10072 (define_insn "*if_move_shift"
10073 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10074 (if_then_else:SI
10075 (match_operator 5 "arm_comparison_operator"
10076 [(match_operand 6 "cc_register" "") (const_int 0)])
10077 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10078 (match_operator:SI 4 "shift_operator"
10079 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10080 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10081 "TARGET_ARM"
10082 "@
10083 mov%D5\\t%0, %2%S4
10084 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10085 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10086 [(set_attr "conds" "use")
10087 (set_attr "shift" "2")
10088 (set_attr "length" "4,8,8")
10089 (set_attr_alternative "type"
10090 [(if_then_else (match_operand 3 "const_int_operand" "")
10091 (const_string "mov_shift" )
10092 (const_string "mov_shift_reg"))
10093 (const_string "multiple")
10094 (const_string "multiple")])]
10095 )
10096
10097 (define_insn "*ifcompare_shift_shift"
10098 [(set (match_operand:SI 0 "s_register_operand" "=r")
10099 (if_then_else:SI
10100 (match_operator 7 "arm_comparison_operator"
10101 [(match_operand:SI 5 "s_register_operand" "r")
10102 (match_operand:SI 6 "arm_add_operand" "rIL")])
10103 (match_operator:SI 8 "shift_operator"
10104 [(match_operand:SI 1 "s_register_operand" "r")
10105 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10106 (match_operator:SI 9 "shift_operator"
10107 [(match_operand:SI 3 "s_register_operand" "r")
10108 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10109 (clobber (reg:CC CC_REGNUM))]
10110 "TARGET_ARM"
10111 "#"
10112 [(set_attr "conds" "clob")
10113 (set_attr "length" "12")
10114 (set_attr "type" "multiple")]
10115 )
10116
10117 (define_insn "*if_shift_shift"
10118 [(set (match_operand:SI 0 "s_register_operand" "=r")
10119 (if_then_else:SI
10120 (match_operator 5 "arm_comparison_operator"
10121 [(match_operand 8 "cc_register" "") (const_int 0)])
10122 (match_operator:SI 6 "shift_operator"
10123 [(match_operand:SI 1 "s_register_operand" "r")
10124 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10125 (match_operator:SI 7 "shift_operator"
10126 [(match_operand:SI 3 "s_register_operand" "r")
10127 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10128 "TARGET_ARM"
10129 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10130 [(set_attr "conds" "use")
10131 (set_attr "shift" "1")
10132 (set_attr "length" "8")
10133 (set (attr "type") (if_then_else
10134 (and (match_operand 2 "const_int_operand" "")
10135 (match_operand 4 "const_int_operand" ""))
10136 (const_string "mov_shift")
10137 (const_string "mov_shift_reg")))]
10138 )
10139
10140 (define_insn "*ifcompare_not_arith"
10141 [(set (match_operand:SI 0 "s_register_operand" "=r")
10142 (if_then_else:SI
10143 (match_operator 6 "arm_comparison_operator"
10144 [(match_operand:SI 4 "s_register_operand" "r")
10145 (match_operand:SI 5 "arm_add_operand" "rIL")])
10146 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10147 (match_operator:SI 7 "shiftable_operator"
10148 [(match_operand:SI 2 "s_register_operand" "r")
10149 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10150 (clobber (reg:CC CC_REGNUM))]
10151 "TARGET_ARM"
10152 "#"
10153 [(set_attr "conds" "clob")
10154 (set_attr "length" "12")
10155 (set_attr "type" "multiple")]
10156 )
10157
10158 (define_insn "*if_not_arith"
10159 [(set (match_operand:SI 0 "s_register_operand" "=r")
10160 (if_then_else:SI
10161 (match_operator 5 "arm_comparison_operator"
10162 [(match_operand 4 "cc_register" "") (const_int 0)])
10163 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10164 (match_operator:SI 6 "shiftable_operator"
10165 [(match_operand:SI 2 "s_register_operand" "r")
10166 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10167 "TARGET_ARM"
10168 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10169 [(set_attr "conds" "use")
10170 (set_attr "type" "mvn_reg")
10171 (set_attr "length" "8")]
10172 )
10173
10174 (define_insn "*ifcompare_arith_not"
10175 [(set (match_operand:SI 0 "s_register_operand" "=r")
10176 (if_then_else:SI
10177 (match_operator 6 "arm_comparison_operator"
10178 [(match_operand:SI 4 "s_register_operand" "r")
10179 (match_operand:SI 5 "arm_add_operand" "rIL")])
10180 (match_operator:SI 7 "shiftable_operator"
10181 [(match_operand:SI 2 "s_register_operand" "r")
10182 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10183 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10184 (clobber (reg:CC CC_REGNUM))]
10185 "TARGET_ARM"
10186 "#"
10187 [(set_attr "conds" "clob")
10188 (set_attr "length" "12")
10189 (set_attr "type" "multiple")]
10190 )
10191
10192 (define_insn "*if_arith_not"
10193 [(set (match_operand:SI 0 "s_register_operand" "=r")
10194 (if_then_else:SI
10195 (match_operator 5 "arm_comparison_operator"
10196 [(match_operand 4 "cc_register" "") (const_int 0)])
10197 (match_operator:SI 6 "shiftable_operator"
10198 [(match_operand:SI 2 "s_register_operand" "r")
10199 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10200 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10201 "TARGET_ARM"
10202 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10203 [(set_attr "conds" "use")
10204 (set_attr "type" "multiple")
10205 (set_attr "length" "8")]
10206 )
10207
10208 (define_insn "*ifcompare_neg_move"
10209 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10210 (if_then_else:SI
10211 (match_operator 5 "arm_comparison_operator"
10212 [(match_operand:SI 3 "s_register_operand" "r,r")
10213 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10214 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10215 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10216 (clobber (reg:CC CC_REGNUM))]
10217 "TARGET_ARM"
10218 "#"
10219 [(set_attr "conds" "clob")
10220 (set_attr "length" "8,12")
10221 (set_attr "type" "multiple")]
10222 )
10223
10224 (define_insn_and_split "*if_neg_move"
10225 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10226 (if_then_else:SI
10227 (match_operator 4 "arm_comparison_operator"
10228 [(match_operand 3 "cc_register" "") (const_int 0)])
10229 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10230 (match_operand:SI 1 "s_register_operand" "0,0")))]
10231 "TARGET_32BIT"
10232 "#"
10233 "&& reload_completed"
10234 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10235 (set (match_dup 0) (neg:SI (match_dup 2))))]
10236 ""
10237 [(set_attr "conds" "use")
10238 (set_attr "length" "4")
10239 (set_attr "arch" "t2,32")
10240 (set_attr "enabled_for_short_it" "yes,no")
10241 (set_attr "type" "logic_shift_imm")]
10242 )
10243
10244 (define_insn "*ifcompare_move_neg"
10245 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10246 (if_then_else:SI
10247 (match_operator 5 "arm_comparison_operator"
10248 [(match_operand:SI 3 "s_register_operand" "r,r")
10249 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10250 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10251 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10252 (clobber (reg:CC CC_REGNUM))]
10253 "TARGET_ARM"
10254 "#"
10255 [(set_attr "conds" "clob")
10256 (set_attr "length" "8,12")
10257 (set_attr "type" "multiple")]
10258 )
10259
10260 (define_insn_and_split "*if_move_neg"
10261 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10262 (if_then_else:SI
10263 (match_operator 4 "arm_comparison_operator"
10264 [(match_operand 3 "cc_register" "") (const_int 0)])
10265 (match_operand:SI 1 "s_register_operand" "0,0")
10266 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10267 "TARGET_32BIT"
10268 "#"
10269 "&& reload_completed"
10270 [(cond_exec (match_dup 5)
10271 (set (match_dup 0) (neg:SI (match_dup 2))))]
10272 {
10273 machine_mode mode = GET_MODE (operands[3]);
10274 rtx_code rc = GET_CODE (operands[4]);
10275
10276 if (mode == CCFPmode || mode == CCFPEmode)
10277 rc = reverse_condition_maybe_unordered (rc);
10278 else
10279 rc = reverse_condition (rc);
10280
10281 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10282 }
10283 [(set_attr "conds" "use")
10284 (set_attr "length" "4")
10285 (set_attr "arch" "t2,32")
10286 (set_attr "enabled_for_short_it" "yes,no")
10287 (set_attr "type" "logic_shift_imm")]
10288 )
10289
10290 (define_insn "*arith_adjacentmem"
10291 [(set (match_operand:SI 0 "s_register_operand" "=r")
10292 (match_operator:SI 1 "shiftable_operator"
10293 [(match_operand:SI 2 "memory_operand" "m")
10294 (match_operand:SI 3 "memory_operand" "m")]))
10295 (clobber (match_scratch:SI 4 "=r"))]
10296 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10297 "*
10298 {
10299 rtx ldm[3];
10300 rtx arith[4];
10301 rtx base_reg;
10302 HOST_WIDE_INT val1 = 0, val2 = 0;
10303
10304 if (REGNO (operands[0]) > REGNO (operands[4]))
10305 {
10306 ldm[1] = operands[4];
10307 ldm[2] = operands[0];
10308 }
10309 else
10310 {
10311 ldm[1] = operands[0];
10312 ldm[2] = operands[4];
10313 }
10314
10315 base_reg = XEXP (operands[2], 0);
10316
10317 if (!REG_P (base_reg))
10318 {
10319 val1 = INTVAL (XEXP (base_reg, 1));
10320 base_reg = XEXP (base_reg, 0);
10321 }
10322
10323 if (!REG_P (XEXP (operands[3], 0)))
10324 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10325
10326 arith[0] = operands[0];
10327 arith[3] = operands[1];
10328
10329 if (val1 < val2)
10330 {
10331 arith[1] = ldm[1];
10332 arith[2] = ldm[2];
10333 }
10334 else
10335 {
10336 arith[1] = ldm[2];
10337 arith[2] = ldm[1];
10338 }
10339
10340 ldm[0] = base_reg;
10341 if (val1 !=0 && val2 != 0)
10342 {
10343 rtx ops[3];
10344
10345 if (val1 == 4 || val2 == 4)
10346 /* Other val must be 8, since we know they are adjacent and neither
10347 is zero. */
10348 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
10349 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10350 {
10351 ldm[0] = ops[0] = operands[4];
10352 ops[1] = base_reg;
10353 ops[2] = GEN_INT (val1);
10354 output_add_immediate (ops);
10355 if (val1 < val2)
10356 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10357 else
10358 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10359 }
10360 else
10361 {
10362 /* Offset is out of range for a single add, so use two ldr. */
10363 ops[0] = ldm[1];
10364 ops[1] = base_reg;
10365 ops[2] = GEN_INT (val1);
10366 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10367 ops[0] = ldm[2];
10368 ops[2] = GEN_INT (val2);
10369 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10370 }
10371 }
10372 else if (val1 != 0)
10373 {
10374 if (val1 < val2)
10375 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10376 else
10377 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10378 }
10379 else
10380 {
10381 if (val1 < val2)
10382 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10383 else
10384 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10385 }
10386 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10387 return \"\";
10388 }"
10389 [(set_attr "length" "12")
10390 (set_attr "predicable" "yes")
10391 (set_attr "type" "load_4")]
10392 )
10393
10394 ; This pattern is never tried by combine, so do it as a peephole
10395
10396 (define_peephole2
10397 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10398 (match_operand:SI 1 "arm_general_register_operand" ""))
10399 (set (reg:CC CC_REGNUM)
10400 (compare:CC (match_dup 1) (const_int 0)))]
10401 "TARGET_ARM"
10402 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10403 (set (match_dup 0) (match_dup 1))])]
10404 ""
10405 )
10406
10407 (define_split
10408 [(set (match_operand:SI 0 "s_register_operand" "")
10409 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10410 (const_int 0))
10411 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10412 [(match_operand:SI 3 "s_register_operand" "")
10413 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10414 (clobber (match_operand:SI 5 "s_register_operand" ""))]
10415 "TARGET_ARM"
10416 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10417 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10418 (match_dup 5)))]
10419 ""
10420 )
10421
10422 ;; This split can be used because CC_Z mode implies that the following
10423 ;; branch will be an equality, or an unsigned inequality, so the sign
10424 ;; extension is not needed.
10425
10426 (define_split
10427 [(set (reg:CC_Z CC_REGNUM)
10428 (compare:CC_Z
10429 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10430 (const_int 24))
10431 (match_operand 1 "const_int_operand" "")))
10432 (clobber (match_scratch:SI 2 ""))]
10433 "TARGET_ARM
10434 && ((UINTVAL (operands[1]))
10435 == ((UINTVAL (operands[1])) >> 24) << 24)"
10436 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10437 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10438 "
10439 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10440 "
10441 )
10442 ;; ??? Check the patterns above for Thumb-2 usefulness
10443
10444 (define_expand "prologue"
10445 [(clobber (const_int 0))]
10446 "TARGET_EITHER"
10447 "if (TARGET_32BIT)
10448 arm_expand_prologue ();
10449 else
10450 thumb1_expand_prologue ();
10451 DONE;
10452 "
10453 )
10454
10455 (define_expand "epilogue"
10456 [(clobber (const_int 0))]
10457 "TARGET_EITHER"
10458 "
10459 if (crtl->calls_eh_return)
10460 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
10461 if (TARGET_THUMB1)
10462 {
10463 thumb1_expand_epilogue ();
10464 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10465 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10466 }
10467 else if (HAVE_return)
10468 {
10469 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10470 no need for explicit testing again. */
10471 emit_jump_insn (gen_return ());
10472 }
10473 else if (TARGET_32BIT)
10474 {
10475 arm_expand_epilogue (true);
10476 }
10477 DONE;
10478 "
10479 )
10480
10481 ;; Note - although unspec_volatile's USE all hard registers,
10482 ;; USEs are ignored after relaod has completed. Thus we need
10483 ;; to add an unspec of the link register to ensure that flow
10484 ;; does not think that it is unused by the sibcall branch that
10485 ;; will replace the standard function epilogue.
10486 (define_expand "sibcall_epilogue"
10487 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
10488 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10489 "TARGET_32BIT"
10490 "
10491 arm_expand_epilogue (false);
10492 DONE;
10493 "
10494 )
10495
10496 (define_expand "eh_epilogue"
10497 [(use (match_operand:SI 0 "register_operand"))
10498 (use (match_operand:SI 1 "register_operand"))
10499 (use (match_operand:SI 2 "register_operand"))]
10500 "TARGET_EITHER"
10501 "
10502 {
10503 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10504 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
10505 {
10506 rtx ra = gen_rtx_REG (Pmode, 2);
10507
10508 emit_move_insn (ra, operands[2]);
10509 operands[2] = ra;
10510 }
10511 /* This is a hack -- we may have crystalized the function type too
10512 early. */
10513 cfun->machine->func_type = 0;
10514 }"
10515 )
10516
10517 ;; This split is only used during output to reduce the number of patterns
10518 ;; that need assembler instructions adding to them. We allowed the setting
10519 ;; of the conditions to be implicit during rtl generation so that
10520 ;; the conditional compare patterns would work. However this conflicts to
10521 ;; some extent with the conditional data operations, so we have to split them
10522 ;; up again here.
10523
10524 ;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10525 ;; conditional execution sufficient?
10526
10527 (define_split
10528 [(set (match_operand:SI 0 "s_register_operand" "")
10529 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10530 [(match_operand 2 "" "") (match_operand 3 "" "")])
10531 (match_dup 0)
10532 (match_operand 4 "" "")))
10533 (clobber (reg:CC CC_REGNUM))]
10534 "TARGET_ARM && reload_completed"
10535 [(set (match_dup 5) (match_dup 6))
10536 (cond_exec (match_dup 7)
10537 (set (match_dup 0) (match_dup 4)))]
10538 "
10539 {
10540 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10541 operands[2], operands[3]);
10542 enum rtx_code rc = GET_CODE (operands[1]);
10543
10544 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10545 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10546 if (mode == CCFPmode || mode == CCFPEmode)
10547 rc = reverse_condition_maybe_unordered (rc);
10548 else
10549 rc = reverse_condition (rc);
10550
10551 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10552 }"
10553 )
10554
10555 (define_split
10556 [(set (match_operand:SI 0 "s_register_operand" "")
10557 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10558 [(match_operand 2 "" "") (match_operand 3 "" "")])
10559 (match_operand 4 "" "")
10560 (match_dup 0)))
10561 (clobber (reg:CC CC_REGNUM))]
10562 "TARGET_ARM && reload_completed"
10563 [(set (match_dup 5) (match_dup 6))
10564 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10565 (set (match_dup 0) (match_dup 4)))]
10566 "
10567 {
10568 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10569 operands[2], operands[3]);
10570
10571 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10572 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10573 }"
10574 )
10575
10576 (define_split
10577 [(set (match_operand:SI 0 "s_register_operand" "")
10578 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10579 [(match_operand 2 "" "") (match_operand 3 "" "")])
10580 (match_operand 4 "" "")
10581 (match_operand 5 "" "")))
10582 (clobber (reg:CC CC_REGNUM))]
10583 "TARGET_ARM && reload_completed"
10584 [(set (match_dup 6) (match_dup 7))
10585 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10586 (set (match_dup 0) (match_dup 4)))
10587 (cond_exec (match_dup 8)
10588 (set (match_dup 0) (match_dup 5)))]
10589 "
10590 {
10591 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10592 operands[2], operands[3]);
10593 enum rtx_code rc = GET_CODE (operands[1]);
10594
10595 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10596 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10597 if (mode == CCFPmode || mode == CCFPEmode)
10598 rc = reverse_condition_maybe_unordered (rc);
10599 else
10600 rc = reverse_condition (rc);
10601
10602 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10603 }"
10604 )
10605
10606 (define_split
10607 [(set (match_operand:SI 0 "s_register_operand" "")
10608 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10609 [(match_operand:SI 2 "s_register_operand" "")
10610 (match_operand:SI 3 "arm_add_operand" "")])
10611 (match_operand:SI 4 "arm_rhs_operand" "")
10612 (not:SI
10613 (match_operand:SI 5 "s_register_operand" ""))))
10614 (clobber (reg:CC CC_REGNUM))]
10615 "TARGET_ARM && reload_completed"
10616 [(set (match_dup 6) (match_dup 7))
10617 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10618 (set (match_dup 0) (match_dup 4)))
10619 (cond_exec (match_dup 8)
10620 (set (match_dup 0) (not:SI (match_dup 5))))]
10621 "
10622 {
10623 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10624 operands[2], operands[3]);
10625 enum rtx_code rc = GET_CODE (operands[1]);
10626
10627 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10628 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10629 if (mode == CCFPmode || mode == CCFPEmode)
10630 rc = reverse_condition_maybe_unordered (rc);
10631 else
10632 rc = reverse_condition (rc);
10633
10634 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10635 }"
10636 )
10637
10638 (define_insn "*cond_move_not"
10639 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10640 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10641 [(match_operand 3 "cc_register" "") (const_int 0)])
10642 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10643 (not:SI
10644 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10645 "TARGET_ARM"
10646 "@
10647 mvn%D4\\t%0, %2
10648 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10649 [(set_attr "conds" "use")
10650 (set_attr "type" "mvn_reg,multiple")
10651 (set_attr "length" "4,8")]
10652 )
10653
10654 ;; The next two patterns occur when an AND operation is followed by a
10655 ;; scc insn sequence
10656
10657 (define_insn "*sign_extract_onebit"
10658 [(set (match_operand:SI 0 "s_register_operand" "=r")
10659 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10660 (const_int 1)
10661 (match_operand:SI 2 "const_int_operand" "n")))
10662 (clobber (reg:CC CC_REGNUM))]
10663 "TARGET_ARM"
10664 "*
10665 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10666 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10667 return \"mvnne\\t%0, #0\";
10668 "
10669 [(set_attr "conds" "clob")
10670 (set_attr "length" "8")
10671 (set_attr "type" "multiple")]
10672 )
10673
10674 (define_insn "*not_signextract_onebit"
10675 [(set (match_operand:SI 0 "s_register_operand" "=r")
10676 (not:SI
10677 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10678 (const_int 1)
10679 (match_operand:SI 2 "const_int_operand" "n"))))
10680 (clobber (reg:CC CC_REGNUM))]
10681 "TARGET_ARM"
10682 "*
10683 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10684 output_asm_insn (\"tst\\t%1, %2\", operands);
10685 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10686 return \"movne\\t%0, #0\";
10687 "
10688 [(set_attr "conds" "clob")
10689 (set_attr "length" "12")
10690 (set_attr "type" "multiple")]
10691 )
10692 ;; ??? The above patterns need auditing for Thumb-2
10693
10694 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10695 ;; expressions. For simplicity, the first register is also in the unspec
10696 ;; part.
10697 ;; To avoid the usage of GNU extension, the length attribute is computed
10698 ;; in a C function arm_attr_length_push_multi.
10699 (define_insn "*push_multi"
10700 [(match_parallel 2 "multi_register_push"
10701 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10702 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10703 UNSPEC_PUSH_MULT))])]
10704 ""
10705 "*
10706 {
10707 int num_saves = XVECLEN (operands[2], 0);
10708
10709 /* For the StrongARM at least it is faster to
10710 use STR to store only a single register.
10711 In Thumb mode always use push, and the assembler will pick
10712 something appropriate. */
10713 if (num_saves == 1 && TARGET_ARM)
10714 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
10715 else
10716 {
10717 int i;
10718 char pattern[100];
10719
10720 if (TARGET_32BIT)
10721 strcpy (pattern, \"push%?\\t{%1\");
10722 else
10723 strcpy (pattern, \"push\\t{%1\");
10724
10725 for (i = 1; i < num_saves; i++)
10726 {
10727 strcat (pattern, \", %|\");
10728 strcat (pattern,
10729 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10730 }
10731
10732 strcat (pattern, \"}\");
10733 output_asm_insn (pattern, operands);
10734 }
10735
10736 return \"\";
10737 }"
10738 [(set_attr "type" "store_16")
10739 (set (attr "length")
10740 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
10741 )
10742
10743 (define_insn "stack_tie"
10744 [(set (mem:BLK (scratch))
10745 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10746 (match_operand:SI 1 "s_register_operand" "rk")]
10747 UNSPEC_PRLG_STK))]
10748 ""
10749 ""
10750 [(set_attr "length" "0")
10751 (set_attr "type" "block")]
10752 )
10753
10754 ;; Pop (as used in epilogue RTL)
10755 ;;
10756 (define_insn "*load_multiple_with_writeback"
10757 [(match_parallel 0 "load_multiple_operation"
10758 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10759 (plus:SI (match_dup 1)
10760 (match_operand:SI 2 "const_int_I_operand" "I")))
10761 (set (match_operand:SI 3 "s_register_operand" "=rk")
10762 (mem:SI (match_dup 1)))
10763 ])]
10764 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10765 "*
10766 {
10767 arm_output_multireg_pop (operands, /*return_pc=*/false,
10768 /*cond=*/const_true_rtx,
10769 /*reverse=*/false,
10770 /*update=*/true);
10771 return \"\";
10772 }
10773 "
10774 [(set_attr "type" "load_16")
10775 (set_attr "predicable" "yes")
10776 (set (attr "length")
10777 (symbol_ref "arm_attr_length_pop_multi (operands,
10778 /*return_pc=*/false,
10779 /*write_back_p=*/true)"))]
10780 )
10781
10782 ;; Pop with return (as used in epilogue RTL)
10783 ;;
10784 ;; This instruction is generated when the registers are popped at the end of
10785 ;; epilogue. Here, instead of popping the value into LR and then generating
10786 ;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10787 ;; with (return).
10788 (define_insn "*pop_multiple_with_writeback_and_return"
10789 [(match_parallel 0 "pop_multiple_return"
10790 [(return)
10791 (set (match_operand:SI 1 "s_register_operand" "+rk")
10792 (plus:SI (match_dup 1)
10793 (match_operand:SI 2 "const_int_I_operand" "I")))
10794 (set (match_operand:SI 3 "s_register_operand" "=rk")
10795 (mem:SI (match_dup 1)))
10796 ])]
10797 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10798 "*
10799 {
10800 arm_output_multireg_pop (operands, /*return_pc=*/true,
10801 /*cond=*/const_true_rtx,
10802 /*reverse=*/false,
10803 /*update=*/true);
10804 return \"\";
10805 }
10806 "
10807 [(set_attr "type" "load_16")
10808 (set_attr "predicable" "yes")
10809 (set (attr "length")
10810 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10811 /*write_back_p=*/true)"))]
10812 )
10813
10814 (define_insn "*pop_multiple_with_return"
10815 [(match_parallel 0 "pop_multiple_return"
10816 [(return)
10817 (set (match_operand:SI 2 "s_register_operand" "=rk")
10818 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10819 ])]
10820 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10821 "*
10822 {
10823 arm_output_multireg_pop (operands, /*return_pc=*/true,
10824 /*cond=*/const_true_rtx,
10825 /*reverse=*/false,
10826 /*update=*/false);
10827 return \"\";
10828 }
10829 "
10830 [(set_attr "type" "load_16")
10831 (set_attr "predicable" "yes")
10832 (set (attr "length")
10833 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10834 /*write_back_p=*/false)"))]
10835 )
10836
10837 ;; Load into PC and return
10838 (define_insn "*ldr_with_return"
10839 [(return)
10840 (set (reg:SI PC_REGNUM)
10841 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10842 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10843 "ldr%?\t%|pc, [%0], #4"
10844 [(set_attr "type" "load_4")
10845 (set_attr "predicable" "yes")]
10846 )
10847 ;; Pop for floating point registers (as used in epilogue RTL)
10848 (define_insn "*vfp_pop_multiple_with_writeback"
10849 [(match_parallel 0 "pop_multiple_fp"
10850 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10851 (plus:SI (match_dup 1)
10852 (match_operand:SI 2 "const_int_I_operand" "I")))
10853 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
10854 (mem:DF (match_dup 1)))])]
10855 "TARGET_32BIT && TARGET_HARD_FLOAT"
10856 "*
10857 {
10858 int num_regs = XVECLEN (operands[0], 0);
10859 char pattern[100];
10860 rtx op_list[2];
10861 strcpy (pattern, \"vldm\\t\");
10862 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10863 strcat (pattern, \"!, {\");
10864 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10865 strcat (pattern, \"%P0\");
10866 if ((num_regs - 1) > 1)
10867 {
10868 strcat (pattern, \"-%P1\");
10869 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10870 }
10871
10872 strcat (pattern, \"}\");
10873 output_asm_insn (pattern, op_list);
10874 return \"\";
10875 }
10876 "
10877 [(set_attr "type" "load_16")
10878 (set_attr "conds" "unconditional")
10879 (set_attr "predicable" "no")]
10880 )
10881
10882 ;; Special patterns for dealing with the constant pool
10883
10884 (define_insn "align_4"
10885 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10886 "TARGET_EITHER"
10887 "*
10888 assemble_align (32);
10889 return \"\";
10890 "
10891 [(set_attr "type" "no_insn")]
10892 )
10893
10894 (define_insn "align_8"
10895 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10896 "TARGET_EITHER"
10897 "*
10898 assemble_align (64);
10899 return \"\";
10900 "
10901 [(set_attr "type" "no_insn")]
10902 )
10903
10904 (define_insn "consttable_end"
10905 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10906 "TARGET_EITHER"
10907 "*
10908 making_const_table = FALSE;
10909 return \"\";
10910 "
10911 [(set_attr "type" "no_insn")]
10912 )
10913
10914 (define_insn "consttable_1"
10915 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10916 "TARGET_EITHER"
10917 "*
10918 making_const_table = TRUE;
10919 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10920 assemble_zeros (3);
10921 return \"\";
10922 "
10923 [(set_attr "length" "4")
10924 (set_attr "type" "no_insn")]
10925 )
10926
10927 (define_insn "consttable_2"
10928 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10929 "TARGET_EITHER"
10930 "*
10931 {
10932 rtx x = operands[0];
10933 making_const_table = TRUE;
10934 switch (GET_MODE_CLASS (GET_MODE (x)))
10935 {
10936 case MODE_FLOAT:
10937 arm_emit_fp16_const (x);
10938 break;
10939 default:
10940 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10941 assemble_zeros (2);
10942 break;
10943 }
10944 return \"\";
10945 }"
10946 [(set_attr "length" "4")
10947 (set_attr "type" "no_insn")]
10948 )
10949
10950 (define_insn "consttable_4"
10951 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10952 "TARGET_EITHER"
10953 "*
10954 {
10955 rtx x = operands[0];
10956 making_const_table = TRUE;
10957 scalar_float_mode float_mode;
10958 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
10959 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
10960 else
10961 {
10962 /* XXX: Sometimes gcc does something really dumb and ends up with
10963 a HIGH in a constant pool entry, usually because it's trying to
10964 load into a VFP register. We know this will always be used in
10965 combination with a LO_SUM which ignores the high bits, so just
10966 strip off the HIGH. */
10967 if (GET_CODE (x) == HIGH)
10968 x = XEXP (x, 0);
10969 assemble_integer (x, 4, BITS_PER_WORD, 1);
10970 mark_symbol_refs_as_used (x);
10971 }
10972 return \"\";
10973 }"
10974 [(set_attr "length" "4")
10975 (set_attr "type" "no_insn")]
10976 )
10977
10978 (define_insn "consttable_8"
10979 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10980 "TARGET_EITHER"
10981 "*
10982 {
10983 making_const_table = TRUE;
10984 scalar_float_mode float_mode;
10985 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10986 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10987 float_mode, BITS_PER_WORD);
10988 else
10989 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10990 return \"\";
10991 }"
10992 [(set_attr "length" "8")
10993 (set_attr "type" "no_insn")]
10994 )
10995
10996 (define_insn "consttable_16"
10997 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10998 "TARGET_EITHER"
10999 "*
11000 {
11001 making_const_table = TRUE;
11002 scalar_float_mode float_mode;
11003 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11004 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11005 float_mode, BITS_PER_WORD);
11006 else
11007 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11008 return \"\";
11009 }"
11010 [(set_attr "length" "16")
11011 (set_attr "type" "no_insn")]
11012 )
11013
11014 ;; V5 Instructions,
11015
11016 (define_insn "clzsi2"
11017 [(set (match_operand:SI 0 "s_register_operand" "=r")
11018 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11019 "TARGET_32BIT && arm_arch5t"
11020 "clz%?\\t%0, %1"
11021 [(set_attr "predicable" "yes")
11022 (set_attr "type" "clz")])
11023
11024 (define_insn "rbitsi2"
11025 [(set (match_operand:SI 0 "s_register_operand" "=r")
11026 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11027 "TARGET_32BIT && arm_arch_thumb2"
11028 "rbit%?\\t%0, %1"
11029 [(set_attr "predicable" "yes")
11030 (set_attr "type" "clz")])
11031
11032 ;; Keep this as a CTZ expression until after reload and then split
11033 ;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11034 ;; to fold with any other expression.
11035
11036 (define_insn_and_split "ctzsi2"
11037 [(set (match_operand:SI 0 "s_register_operand" "=r")
11038 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11039 "TARGET_32BIT && arm_arch_thumb2"
11040 "#"
11041 "&& reload_completed"
11042 [(const_int 0)]
11043 "
11044 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11045 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11046 DONE;
11047 ")
11048
11049 ;; V5E instructions.
11050
11051 (define_insn "prefetch"
11052 [(prefetch (match_operand:SI 0 "address_operand" "p")
11053 (match_operand:SI 1 "" "")
11054 (match_operand:SI 2 "" ""))]
11055 "TARGET_32BIT && arm_arch5te"
11056 "pld\\t%a0"
11057 [(set_attr "type" "load_4")]
11058 )
11059
11060 ;; General predication pattern
11061
11062 (define_cond_exec
11063 [(match_operator 0 "arm_comparison_operator"
11064 [(match_operand 1 "cc_register" "")
11065 (const_int 0)])]
11066 "TARGET_32BIT
11067 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
11068 ""
11069 [(set_attr "predicated" "yes")]
11070 )
11071
11072 (define_insn "force_register_use"
11073 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
11074 ""
11075 "%@ %0 needed"
11076 [(set_attr "length" "0")
11077 (set_attr "type" "no_insn")]
11078 )
11079
11080
11081 ;; Patterns for exception handling
11082
11083 (define_expand "eh_return"
11084 [(use (match_operand 0 "general_operand"))]
11085 "TARGET_EITHER"
11086 "
11087 {
11088 if (TARGET_32BIT)
11089 emit_insn (gen_arm_eh_return (operands[0]));
11090 else
11091 emit_insn (gen_thumb_eh_return (operands[0]));
11092 DONE;
11093 }"
11094 )
11095
11096 ;; We can't expand this before we know where the link register is stored.
11097 (define_insn_and_split "arm_eh_return"
11098 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11099 VUNSPEC_EH_RETURN)
11100 (clobber (match_scratch:SI 1 "=&r"))]
11101 "TARGET_ARM"
11102 "#"
11103 "&& reload_completed"
11104 [(const_int 0)]
11105 "
11106 {
11107 arm_set_return_address (operands[0], operands[1]);
11108 DONE;
11109 }"
11110 )
11111
11112 \f
11113 ;; TLS support
11114
11115 (define_insn "load_tp_hard"
11116 [(set (match_operand:SI 0 "register_operand" "=r")
11117 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11118 "TARGET_HARD_TP"
11119 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11120 [(set_attr "predicable" "yes")
11121 (set_attr "type" "mrs")]
11122 )
11123
11124 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11125 (define_insn "load_tp_soft_fdpic"
11126 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11127 (clobber (reg:SI FDPIC_REGNUM))
11128 (clobber (reg:SI LR_REGNUM))
11129 (clobber (reg:SI IP_REGNUM))
11130 (clobber (reg:CC CC_REGNUM))]
11131 "TARGET_SOFT_TP && TARGET_FDPIC"
11132 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11133 [(set_attr "conds" "clob")
11134 (set_attr "type" "branch")]
11135 )
11136
11137 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11138 (define_insn "load_tp_soft"
11139 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11140 (clobber (reg:SI LR_REGNUM))
11141 (clobber (reg:SI IP_REGNUM))
11142 (clobber (reg:CC CC_REGNUM))]
11143 "TARGET_SOFT_TP && !TARGET_FDPIC"
11144 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11145 [(set_attr "conds" "clob")
11146 (set_attr "type" "branch")]
11147 )
11148
11149 ;; tls descriptor call
11150 (define_insn "tlscall"
11151 [(set (reg:SI R0_REGNUM)
11152 (unspec:SI [(reg:SI R0_REGNUM)
11153 (match_operand:SI 0 "" "X")
11154 (match_operand 1 "" "")] UNSPEC_TLS))
11155 (clobber (reg:SI R1_REGNUM))
11156 (clobber (reg:SI LR_REGNUM))
11157 (clobber (reg:SI CC_REGNUM))]
11158 "TARGET_GNU2_TLS"
11159 {
11160 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11161 INTVAL (operands[1]));
11162 return "bl\\t%c0(tlscall)";
11163 }
11164 [(set_attr "conds" "clob")
11165 (set_attr "length" "4")
11166 (set_attr "type" "branch")]
11167 )
11168
11169 ;; For thread pointer builtin
11170 (define_expand "get_thread_pointersi"
11171 [(match_operand:SI 0 "s_register_operand")]
11172 ""
11173 "
11174 {
11175 arm_load_tp (operands[0]);
11176 DONE;
11177 }")
11178
11179 ;;
11180
11181 ;; We only care about the lower 16 bits of the constant
11182 ;; being inserted into the upper 16 bits of the register.
11183 (define_insn "*arm_movtas_ze"
11184 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
11185 (const_int 16)
11186 (const_int 16))
11187 (match_operand:SI 1 "const_int_operand" ""))]
11188 "TARGET_HAVE_MOVT"
11189 "@
11190 movt%?\t%0, %L1
11191 movt\t%0, %L1"
11192 [(set_attr "arch" "32,v8mb")
11193 (set_attr "predicable" "yes")
11194 (set_attr "length" "4")
11195 (set_attr "type" "alu_sreg")]
11196 )
11197
11198 (define_insn "*arm_rev"
11199 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11200 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11201 "arm_arch6"
11202 "@
11203 rev\t%0, %1
11204 rev%?\t%0, %1
11205 rev%?\t%0, %1"
11206 [(set_attr "arch" "t1,t2,32")
11207 (set_attr "length" "2,2,4")
11208 (set_attr "predicable" "no,yes,yes")
11209 (set_attr "type" "rev")]
11210 )
11211
11212 (define_expand "arm_legacy_rev"
11213 [(set (match_operand:SI 2 "s_register_operand")
11214 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
11215 (const_int 16))
11216 (match_dup 1)))
11217 (set (match_dup 2)
11218 (lshiftrt:SI (match_dup 2)
11219 (const_int 8)))
11220 (set (match_operand:SI 3 "s_register_operand")
11221 (rotatert:SI (match_dup 1)
11222 (const_int 8)))
11223 (set (match_dup 2)
11224 (and:SI (match_dup 2)
11225 (const_int -65281)))
11226 (set (match_operand:SI 0 "s_register_operand")
11227 (xor:SI (match_dup 3)
11228 (match_dup 2)))]
11229 "TARGET_32BIT"
11230 ""
11231 )
11232
11233 ;; Reuse temporaries to keep register pressure down.
11234 (define_expand "thumb_legacy_rev"
11235 [(set (match_operand:SI 2 "s_register_operand")
11236 (ashift:SI (match_operand:SI 1 "s_register_operand")
11237 (const_int 24)))
11238 (set (match_operand:SI 3 "s_register_operand")
11239 (lshiftrt:SI (match_dup 1)
11240 (const_int 24)))
11241 (set (match_dup 3)
11242 (ior:SI (match_dup 3)
11243 (match_dup 2)))
11244 (set (match_operand:SI 4 "s_register_operand")
11245 (const_int 16))
11246 (set (match_operand:SI 5 "s_register_operand")
11247 (rotatert:SI (match_dup 1)
11248 (match_dup 4)))
11249 (set (match_dup 2)
11250 (ashift:SI (match_dup 5)
11251 (const_int 24)))
11252 (set (match_dup 5)
11253 (lshiftrt:SI (match_dup 5)
11254 (const_int 24)))
11255 (set (match_dup 5)
11256 (ior:SI (match_dup 5)
11257 (match_dup 2)))
11258 (set (match_dup 5)
11259 (rotatert:SI (match_dup 5)
11260 (match_dup 4)))
11261 (set (match_operand:SI 0 "s_register_operand")
11262 (ior:SI (match_dup 5)
11263 (match_dup 3)))]
11264 "TARGET_THUMB"
11265 ""
11266 )
11267
11268 ;; ARM-specific expansion of signed mod by power of 2
11269 ;; using conditional negate.
11270 ;; For r0 % n where n is a power of 2 produce:
11271 ;; rsbs r1, r0, #0
11272 ;; and r0, r0, #(n - 1)
11273 ;; and r1, r1, #(n - 1)
11274 ;; rsbpl r0, r1, #0
11275
11276 (define_expand "modsi3"
11277 [(match_operand:SI 0 "register_operand")
11278 (match_operand:SI 1 "register_operand")
11279 (match_operand:SI 2 "const_int_operand")]
11280 "TARGET_32BIT"
11281 {
11282 HOST_WIDE_INT val = INTVAL (operands[2]);
11283
11284 if (val <= 0
11285 || exact_log2 (val) <= 0)
11286 FAIL;
11287
11288 rtx mask = GEN_INT (val - 1);
11289
11290 /* In the special case of x0 % 2 we can do the even shorter:
11291 cmp r0, #0
11292 and r0, r0, #1
11293 rsblt r0, r0, #0. */
11294
11295 if (val == 2)
11296 {
11297 rtx cc_reg = arm_gen_compare_reg (LT,
11298 operands[1], const0_rtx, NULL_RTX);
11299 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11300 rtx masked = gen_reg_rtx (SImode);
11301
11302 emit_insn (gen_andsi3 (masked, operands[1], mask));
11303 emit_move_insn (operands[0],
11304 gen_rtx_IF_THEN_ELSE (SImode, cond,
11305 gen_rtx_NEG (SImode,
11306 masked),
11307 masked));
11308 DONE;
11309 }
11310
11311 rtx neg_op = gen_reg_rtx (SImode);
11312 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11313 operands[1]));
11314
11315 /* Extract the condition register and mode. */
11316 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11317 rtx cc_reg = SET_DEST (cmp);
11318 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11319
11320 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11321
11322 rtx masked_neg = gen_reg_rtx (SImode);
11323 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11324
11325 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11326 during expand does not always work. Do an IF_THEN_ELSE instead. */
11327 emit_move_insn (operands[0],
11328 gen_rtx_IF_THEN_ELSE (SImode, cond,
11329 gen_rtx_NEG (SImode, masked_neg),
11330 operands[0]));
11331
11332
11333 DONE;
11334 }
11335 )
11336
11337 (define_expand "bswapsi2"
11338 [(set (match_operand:SI 0 "s_register_operand")
11339 (bswap:SI (match_operand:SI 1 "s_register_operand")))]
11340 "TARGET_EITHER && (arm_arch6 || !optimize_size)"
11341 "
11342 if (!arm_arch6)
11343 {
11344 rtx op2 = gen_reg_rtx (SImode);
11345 rtx op3 = gen_reg_rtx (SImode);
11346
11347 if (TARGET_THUMB)
11348 {
11349 rtx op4 = gen_reg_rtx (SImode);
11350 rtx op5 = gen_reg_rtx (SImode);
11351
11352 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11353 op2, op3, op4, op5));
11354 }
11355 else
11356 {
11357 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11358 op2, op3));
11359 }
11360
11361 DONE;
11362 }
11363 "
11364 )
11365
11366 ;; bswap16 patterns: use revsh and rev16 instructions for the signed
11367 ;; and unsigned variants, respectively. For rev16, expose
11368 ;; byte-swapping in the lower 16 bits only.
11369 (define_insn "*arm_revsh"
11370 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11371 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11372 "arm_arch6"
11373 "@
11374 revsh\t%0, %1
11375 revsh%?\t%0, %1
11376 revsh%?\t%0, %1"
11377 [(set_attr "arch" "t1,t2,32")
11378 (set_attr "length" "2,2,4")
11379 (set_attr "type" "rev")]
11380 )
11381
11382 (define_insn "*arm_rev16"
11383 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11384 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11385 "arm_arch6"
11386 "@
11387 rev16\t%0, %1
11388 rev16%?\t%0, %1
11389 rev16%?\t%0, %1"
11390 [(set_attr "arch" "t1,t2,32")
11391 (set_attr "length" "2,2,4")
11392 (set_attr "type" "rev")]
11393 )
11394
11395 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11396 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
11397 ;; each valid permutation.
11398
11399 (define_insn "arm_rev16si2"
11400 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11401 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11402 (const_int 8))
11403 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11404 (and:SI (lshiftrt:SI (match_dup 1)
11405 (const_int 8))
11406 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11407 "arm_arch6
11408 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11409 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11410 "rev16\\t%0, %1"
11411 [(set_attr "arch" "t1,t2,32")
11412 (set_attr "length" "2,2,4")
11413 (set_attr "type" "rev")]
11414 )
11415
11416 (define_insn "arm_rev16si2_alt"
11417 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11418 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11419 (const_int 8))
11420 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11421 (and:SI (ashift:SI (match_dup 1)
11422 (const_int 8))
11423 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11424 "arm_arch6
11425 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11426 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11427 "rev16\\t%0, %1"
11428 [(set_attr "arch" "t1,t2,32")
11429 (set_attr "length" "2,2,4")
11430 (set_attr "type" "rev")]
11431 )
11432
11433 (define_expand "bswaphi2"
11434 [(set (match_operand:HI 0 "s_register_operand")
11435 (bswap:HI (match_operand:HI 1 "s_register_operand")))]
11436 "arm_arch6"
11437 ""
11438 )
11439
11440 ;; Patterns for LDRD/STRD in Thumb2 mode
11441
11442 (define_insn "*thumb2_ldrd"
11443 [(set (match_operand:SI 0 "s_register_operand" "=r")
11444 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11445 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11446 (set (match_operand:SI 3 "s_register_operand" "=r")
11447 (mem:SI (plus:SI (match_dup 1)
11448 (match_operand:SI 4 "const_int_operand" ""))))]
11449 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11450 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11451 && (operands_ok_ldrd_strd (operands[0], operands[3],
11452 operands[1], INTVAL (operands[2]),
11453 false, true))"
11454 "ldrd%?\t%0, %3, [%1, %2]"
11455 [(set_attr "type" "load_8")
11456 (set_attr "predicable" "yes")])
11457
11458 (define_insn "*thumb2_ldrd_base"
11459 [(set (match_operand:SI 0 "s_register_operand" "=r")
11460 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11461 (set (match_operand:SI 2 "s_register_operand" "=r")
11462 (mem:SI (plus:SI (match_dup 1)
11463 (const_int 4))))]
11464 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11465 && (operands_ok_ldrd_strd (operands[0], operands[2],
11466 operands[1], 0, false, true))"
11467 "ldrd%?\t%0, %2, [%1]"
11468 [(set_attr "type" "load_8")
11469 (set_attr "predicable" "yes")])
11470
11471 (define_insn "*thumb2_ldrd_base_neg"
11472 [(set (match_operand:SI 0 "s_register_operand" "=r")
11473 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11474 (const_int -4))))
11475 (set (match_operand:SI 2 "s_register_operand" "=r")
11476 (mem:SI (match_dup 1)))]
11477 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11478 && (operands_ok_ldrd_strd (operands[0], operands[2],
11479 operands[1], -4, false, true))"
11480 "ldrd%?\t%0, %2, [%1, #-4]"
11481 [(set_attr "type" "load_8")
11482 (set_attr "predicable" "yes")])
11483
11484 (define_insn "*thumb2_strd"
11485 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11486 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11487 (match_operand:SI 2 "s_register_operand" "r"))
11488 (set (mem:SI (plus:SI (match_dup 0)
11489 (match_operand:SI 3 "const_int_operand" "")))
11490 (match_operand:SI 4 "s_register_operand" "r"))]
11491 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11492 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11493 && (operands_ok_ldrd_strd (operands[2], operands[4],
11494 operands[0], INTVAL (operands[1]),
11495 false, false))"
11496 "strd%?\t%2, %4, [%0, %1]"
11497 [(set_attr "type" "store_8")
11498 (set_attr "predicable" "yes")])
11499
11500 (define_insn "*thumb2_strd_base"
11501 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11502 (match_operand:SI 1 "s_register_operand" "r"))
11503 (set (mem:SI (plus:SI (match_dup 0)
11504 (const_int 4)))
11505 (match_operand:SI 2 "s_register_operand" "r"))]
11506 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11507 && (operands_ok_ldrd_strd (operands[1], operands[2],
11508 operands[0], 0, false, false))"
11509 "strd%?\t%1, %2, [%0]"
11510 [(set_attr "type" "store_8")
11511 (set_attr "predicable" "yes")])
11512
11513 (define_insn "*thumb2_strd_base_neg"
11514 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11515 (const_int -4)))
11516 (match_operand:SI 1 "s_register_operand" "r"))
11517 (set (mem:SI (match_dup 0))
11518 (match_operand:SI 2 "s_register_operand" "r"))]
11519 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11520 && (operands_ok_ldrd_strd (operands[1], operands[2],
11521 operands[0], -4, false, false))"
11522 "strd%?\t%1, %2, [%0, #-4]"
11523 [(set_attr "type" "store_8")
11524 (set_attr "predicable" "yes")])
11525
11526 ;; ARMv8 CRC32 instructions.
11527 (define_insn "arm_<crc_variant>"
11528 [(set (match_operand:SI 0 "s_register_operand" "=r")
11529 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11530 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11531 CRC))]
11532 "TARGET_CRC32"
11533 "<crc_variant>\\t%0, %1, %2"
11534 [(set_attr "type" "crc")
11535 (set_attr "conds" "unconditional")]
11536 )
11537
11538 ;; Load the load/store double peephole optimizations.
11539 (include "ldrdstrd.md")
11540
11541 ;; Load the load/store multiple patterns
11542 (include "ldmstm.md")
11543
11544 ;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11545 ;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11546 ;; The operands are validated through the load_multiple_operation
11547 ;; match_parallel predicate rather than through constraints so enable it only
11548 ;; after reload.
11549 (define_insn "*load_multiple"
11550 [(match_parallel 0 "load_multiple_operation"
11551 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11552 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11553 ])]
11554 "TARGET_32BIT && reload_completed"
11555 "*
11556 {
11557 arm_output_multireg_pop (operands, /*return_pc=*/false,
11558 /*cond=*/const_true_rtx,
11559 /*reverse=*/false,
11560 /*update=*/false);
11561 return \"\";
11562 }
11563 "
11564 [(set_attr "predicable" "yes")]
11565 )
11566
11567 (define_expand "copysignsf3"
11568 [(match_operand:SF 0 "register_operand")
11569 (match_operand:SF 1 "register_operand")
11570 (match_operand:SF 2 "register_operand")]
11571 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11572 "{
11573 emit_move_insn (operands[0], operands[2]);
11574 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11575 GEN_INT (31), GEN_INT (0),
11576 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11577 DONE;
11578 }"
11579 )
11580
11581 (define_expand "copysigndf3"
11582 [(match_operand:DF 0 "register_operand")
11583 (match_operand:DF 1 "register_operand")
11584 (match_operand:DF 2 "register_operand")]
11585 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11586 "{
11587 rtx op0_low = gen_lowpart (SImode, operands[0]);
11588 rtx op0_high = gen_highpart (SImode, operands[0]);
11589 rtx op1_low = gen_lowpart (SImode, operands[1]);
11590 rtx op1_high = gen_highpart (SImode, operands[1]);
11591 rtx op2_high = gen_highpart (SImode, operands[2]);
11592
11593 rtx scratch1 = gen_reg_rtx (SImode);
11594 rtx scratch2 = gen_reg_rtx (SImode);
11595 emit_move_insn (scratch1, op2_high);
11596 emit_move_insn (scratch2, op1_high);
11597
11598 emit_insn(gen_rtx_SET(scratch1,
11599 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11600 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11601 emit_move_insn (op0_low, op1_low);
11602 emit_move_insn (op0_high, scratch2);
11603
11604 DONE;
11605 }"
11606 )
11607
11608 ;; movmisalign patterns for HImode and SImode.
11609 (define_expand "movmisalign<mode>"
11610 [(match_operand:HSI 0 "general_operand")
11611 (match_operand:HSI 1 "general_operand")]
11612 "unaligned_access"
11613 {
11614 /* This pattern is not permitted to fail during expansion: if both arguments
11615 are non-registers (e.g. memory := constant), force operand 1 into a
11616 register. */
11617 rtx (* gen_unaligned_load)(rtx, rtx);
11618 rtx tmp_dest = operands[0];
11619 if (!s_register_operand (operands[0], <MODE>mode)
11620 && !s_register_operand (operands[1], <MODE>mode))
11621 operands[1] = force_reg (<MODE>mode, operands[1]);
11622
11623 if (<MODE>mode == HImode)
11624 {
11625 gen_unaligned_load = gen_unaligned_loadhiu;
11626 tmp_dest = gen_reg_rtx (SImode);
11627 }
11628 else
11629 gen_unaligned_load = gen_unaligned_loadsi;
11630
11631 if (MEM_P (operands[1]))
11632 {
11633 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11634 if (<MODE>mode == HImode)
11635 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11636 }
11637 else
11638 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11639
11640 DONE;
11641 })
11642
11643 (define_insn "arm_<cdp>"
11644 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11645 (match_operand:SI 1 "immediate_operand" "n")
11646 (match_operand:SI 2 "immediate_operand" "n")
11647 (match_operand:SI 3 "immediate_operand" "n")
11648 (match_operand:SI 4 "immediate_operand" "n")
11649 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11650 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11651 {
11652 arm_const_bounds (operands[0], 0, 16);
11653 arm_const_bounds (operands[1], 0, 16);
11654 arm_const_bounds (operands[2], 0, (1 << 5));
11655 arm_const_bounds (operands[3], 0, (1 << 5));
11656 arm_const_bounds (operands[4], 0, (1 << 5));
11657 arm_const_bounds (operands[5], 0, 8);
11658 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11659 }
11660 [(set_attr "length" "4")
11661 (set_attr "type" "coproc")])
11662
11663 (define_insn "*ldc"
11664 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11665 (match_operand:SI 1 "immediate_operand" "n")
11666 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11667 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11668 {
11669 arm_const_bounds (operands[0], 0, 16);
11670 arm_const_bounds (operands[1], 0, (1 << 5));
11671 return "<ldc>\\tp%c0, CR%c1, %2";
11672 }
11673 [(set_attr "length" "4")
11674 (set_attr "type" "coproc")])
11675
11676 (define_insn "*stc"
11677 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11678 (match_operand:SI 1 "immediate_operand" "n")
11679 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11680 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11681 {
11682 arm_const_bounds (operands[0], 0, 16);
11683 arm_const_bounds (operands[1], 0, (1 << 5));
11684 return "<stc>\\tp%c0, CR%c1, %2";
11685 }
11686 [(set_attr "length" "4")
11687 (set_attr "type" "coproc")])
11688
11689 (define_expand "arm_<ldc>"
11690 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11691 (match_operand:SI 1 "immediate_operand")
11692 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11693 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11694
11695 (define_expand "arm_<stc>"
11696 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11697 (match_operand:SI 1 "immediate_operand")
11698 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11699 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11700
11701 (define_insn "arm_<mcr>"
11702 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11703 (match_operand:SI 1 "immediate_operand" "n")
11704 (match_operand:SI 2 "s_register_operand" "r")
11705 (match_operand:SI 3 "immediate_operand" "n")
11706 (match_operand:SI 4 "immediate_operand" "n")
11707 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11708 (use (match_dup 2))]
11709 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11710 {
11711 arm_const_bounds (operands[0], 0, 16);
11712 arm_const_bounds (operands[1], 0, 8);
11713 arm_const_bounds (operands[3], 0, (1 << 5));
11714 arm_const_bounds (operands[4], 0, (1 << 5));
11715 arm_const_bounds (operands[5], 0, 8);
11716 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
11717 }
11718 [(set_attr "length" "4")
11719 (set_attr "type" "coproc")])
11720
11721 (define_insn "arm_<mrc>"
11722 [(set (match_operand:SI 0 "s_register_operand" "=r")
11723 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
11724 (match_operand:SI 2 "immediate_operand" "n")
11725 (match_operand:SI 3 "immediate_operand" "n")
11726 (match_operand:SI 4 "immediate_operand" "n")
11727 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
11728 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
11729 {
11730 arm_const_bounds (operands[1], 0, 16);
11731 arm_const_bounds (operands[2], 0, 8);
11732 arm_const_bounds (operands[3], 0, (1 << 5));
11733 arm_const_bounds (operands[4], 0, (1 << 5));
11734 arm_const_bounds (operands[5], 0, 8);
11735 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
11736 }
11737 [(set_attr "length" "4")
11738 (set_attr "type" "coproc")])
11739
11740 (define_insn "arm_<mcrr>"
11741 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11742 (match_operand:SI 1 "immediate_operand" "n")
11743 (match_operand:DI 2 "s_register_operand" "r")
11744 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
11745 (use (match_dup 2))]
11746 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
11747 {
11748 arm_const_bounds (operands[0], 0, 16);
11749 arm_const_bounds (operands[1], 0, 8);
11750 arm_const_bounds (operands[3], 0, (1 << 5));
11751 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
11752 }
11753 [(set_attr "length" "4")
11754 (set_attr "type" "coproc")])
11755
11756 (define_insn "arm_<mrrc>"
11757 [(set (match_operand:DI 0 "s_register_operand" "=r")
11758 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
11759 (match_operand:SI 2 "immediate_operand" "n")
11760 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
11761 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
11762 {
11763 arm_const_bounds (operands[1], 0, 16);
11764 arm_const_bounds (operands[2], 0, 8);
11765 arm_const_bounds (operands[3], 0, (1 << 5));
11766 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
11767 }
11768 [(set_attr "length" "4")
11769 (set_attr "type" "coproc")])
11770
11771 (define_expand "speculation_barrier"
11772 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11773 "TARGET_EITHER"
11774 "
11775 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
11776 have a usable barrier (and probably don't need one in practice).
11777 But to be safe if such code is run on later architectures, call a
11778 helper function in libgcc that will do the thing for the active
11779 system. */
11780 if (!(arm_arch7 || arm_arch8))
11781 {
11782 arm_emit_speculation_barrier_function ();
11783 DONE;
11784 }
11785 "
11786 )
11787
11788 ;; Generate a hard speculation barrier when we have not enabled speculation
11789 ;; tracking.
11790 (define_insn "*speculation_barrier_insn"
11791 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11792 "arm_arch7 || arm_arch8"
11793 "isb\;dsb\\tsy"
11794 [(set_attr "type" "block")
11795 (set_attr "length" "8")]
11796 )
11797
11798 ;; Vector bits common to IWMMXT and Neon
11799 (include "vec-common.md")
11800 ;; Load the Intel Wireless Multimedia Extension patterns
11801 (include "iwmmxt.md")
11802 ;; Load the VFP co-processor patterns
11803 (include "vfp.md")
11804 ;; Thumb-1 patterns
11805 (include "thumb1.md")
11806 ;; Thumb-2 patterns
11807 (include "thumb2.md")
11808 ;; Neon patterns
11809 (include "neon.md")
11810 ;; Crypto patterns
11811 (include "crypto.md")
11812 ;; Synchronization Primitives
11813 (include "sync.md")
11814 ;; Fixed-point patterns
11815 (include "arm-fixed.md")