]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/arm.md
[ARM] Simplify logical DImode iterators
[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_expand "extendsfdf2"
5062 [(set (match_operand:DF 0 "s_register_operand")
5063 (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
5064 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5065 ""
5066 )
5067
5068 ;; HFmode -> DFmode conversions where we don't have an instruction for it
5069 ;; must go through SFmode.
5070 ;;
5071 ;; This is always safe for an extend.
5072
5073 (define_expand "extendhfdf2"
5074 [(set (match_operand:DF 0 "s_register_operand")
5075 (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
5076 "TARGET_EITHER"
5077 {
5078 /* We don't have a direct instruction for this, so go via SFmode. */
5079 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5080 {
5081 rtx op1;
5082 op1 = convert_to_mode (SFmode, operands[1], 0);
5083 op1 = convert_to_mode (DFmode, op1, 0);
5084 emit_insn (gen_movdf (operands[0], op1));
5085 DONE;
5086 }
5087 /* Otherwise, we're done producing RTL and will pick up the correct
5088 pattern to do this with one rounding-step in a single instruction. */
5089 }
5090 )
5091 \f
5092 ;; Move insns (including loads and stores)
5093
5094 ;; XXX Just some ideas about movti.
5095 ;; I don't think these are a good idea on the arm, there just aren't enough
5096 ;; registers
5097 ;;(define_expand "loadti"
5098 ;; [(set (match_operand:TI 0 "s_register_operand")
5099 ;; (mem:TI (match_operand:SI 1 "address_operand")))]
5100 ;; "" "")
5101
5102 ;;(define_expand "storeti"
5103 ;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
5104 ;; (match_operand:TI 1 "s_register_operand"))]
5105 ;; "" "")
5106
5107 ;;(define_expand "movti"
5108 ;; [(set (match_operand:TI 0 "general_operand")
5109 ;; (match_operand:TI 1 "general_operand"))]
5110 ;; ""
5111 ;; "
5112 ;;{
5113 ;; rtx insn;
5114 ;;
5115 ;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
5116 ;; operands[1] = copy_to_reg (operands[1]);
5117 ;; if (MEM_P (operands[0]))
5118 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5119 ;; else if (MEM_P (operands[1]))
5120 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5121 ;; else
5122 ;; FAIL;
5123 ;;
5124 ;; emit_insn (insn);
5125 ;; DONE;
5126 ;;}")
5127
5128 ;; Recognize garbage generated above.
5129
5130 ;;(define_insn ""
5131 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5132 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5133 ;; ""
5134 ;; "*
5135 ;; {
5136 ;; register mem = (which_alternative < 3);
5137 ;; register const char *template;
5138 ;;
5139 ;; operands[mem] = XEXP (operands[mem], 0);
5140 ;; switch (which_alternative)
5141 ;; {
5142 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5143 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5144 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5145 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5146 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5147 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
5148 ;; }
5149 ;; output_asm_insn (template, operands);
5150 ;; return \"\";
5151 ;; }")
5152
5153 (define_expand "movdi"
5154 [(set (match_operand:DI 0 "general_operand")
5155 (match_operand:DI 1 "general_operand"))]
5156 "TARGET_EITHER"
5157 "
5158 gcc_checking_assert (aligned_operand (operands[0], DImode));
5159 gcc_checking_assert (aligned_operand (operands[1], DImode));
5160 if (can_create_pseudo_p ())
5161 {
5162 if (!REG_P (operands[0]))
5163 operands[1] = force_reg (DImode, operands[1]);
5164 }
5165 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
5166 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
5167 {
5168 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5169 when expanding function calls. */
5170 gcc_assert (can_create_pseudo_p ());
5171 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5172 {
5173 /* Perform load into legal reg pair first, then move. */
5174 rtx reg = gen_reg_rtx (DImode);
5175 emit_insn (gen_movdi (reg, operands[1]));
5176 operands[1] = reg;
5177 }
5178 emit_move_insn (gen_lowpart (SImode, operands[0]),
5179 gen_lowpart (SImode, operands[1]));
5180 emit_move_insn (gen_highpart (SImode, operands[0]),
5181 gen_highpart (SImode, operands[1]));
5182 DONE;
5183 }
5184 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
5185 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
5186 {
5187 /* Avoid STRD's from an odd-numbered register pair in ARM state
5188 when expanding function prologue. */
5189 gcc_assert (can_create_pseudo_p ());
5190 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5191 ? gen_reg_rtx (DImode)
5192 : operands[0];
5193 emit_move_insn (gen_lowpart (SImode, split_dest),
5194 gen_lowpart (SImode, operands[1]));
5195 emit_move_insn (gen_highpart (SImode, split_dest),
5196 gen_highpart (SImode, operands[1]));
5197 if (split_dest != operands[0])
5198 emit_insn (gen_movdi (operands[0], split_dest));
5199 DONE;
5200 }
5201 "
5202 )
5203
5204 (define_insn "*arm_movdi"
5205 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5206 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
5207 "TARGET_32BIT
5208 && !(TARGET_HARD_FLOAT)
5209 && !TARGET_IWMMXT
5210 && ( register_operand (operands[0], DImode)
5211 || register_operand (operands[1], DImode))"
5212 "*
5213 switch (which_alternative)
5214 {
5215 case 0:
5216 case 1:
5217 case 2:
5218 return \"#\";
5219 case 3:
5220 /* Cannot load it directly, split to load it via MOV / MOVT. */
5221 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5222 return \"#\";
5223 /* Fall through. */
5224 default:
5225 return output_move_double (operands, true, NULL);
5226 }
5227 "
5228 [(set_attr "length" "8,12,16,8,8")
5229 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
5230 (set_attr "arm_pool_range" "*,*,*,1020,*")
5231 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5232 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
5233 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5234 )
5235
5236 (define_split
5237 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5238 (match_operand:ANY64 1 "immediate_operand" ""))]
5239 "TARGET_32BIT
5240 && reload_completed
5241 && (arm_disable_literal_pool
5242 || (arm_const_double_inline_cost (operands[1])
5243 <= arm_max_const_double_inline_cost ()))"
5244 [(const_int 0)]
5245 "
5246 arm_split_constant (SET, SImode, curr_insn,
5247 INTVAL (gen_lowpart (SImode, operands[1])),
5248 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5249 arm_split_constant (SET, SImode, curr_insn,
5250 INTVAL (gen_highpart_mode (SImode,
5251 GET_MODE (operands[0]),
5252 operands[1])),
5253 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5254 DONE;
5255 "
5256 )
5257
5258 ; If optimizing for size, or if we have load delay slots, then
5259 ; we want to split the constant into two separate operations.
5260 ; In both cases this may split a trivial part into a single data op
5261 ; leaving a single complex constant to load. We can also get longer
5262 ; offsets in a LDR which means we get better chances of sharing the pool
5263 ; entries. Finally, we can normally do a better job of scheduling
5264 ; LDR instructions than we can with LDM.
5265 ; This pattern will only match if the one above did not.
5266 (define_split
5267 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5268 (match_operand:ANY64 1 "const_double_operand" ""))]
5269 "TARGET_ARM && reload_completed
5270 && arm_const_double_by_parts (operands[1])"
5271 [(set (match_dup 0) (match_dup 1))
5272 (set (match_dup 2) (match_dup 3))]
5273 "
5274 operands[2] = gen_highpart (SImode, operands[0]);
5275 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5276 operands[1]);
5277 operands[0] = gen_lowpart (SImode, operands[0]);
5278 operands[1] = gen_lowpart (SImode, operands[1]);
5279 "
5280 )
5281
5282 (define_split
5283 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5284 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5285 "TARGET_EITHER && reload_completed"
5286 [(set (match_dup 0) (match_dup 1))
5287 (set (match_dup 2) (match_dup 3))]
5288 "
5289 operands[2] = gen_highpart (SImode, operands[0]);
5290 operands[3] = gen_highpart (SImode, operands[1]);
5291 operands[0] = gen_lowpart (SImode, operands[0]);
5292 operands[1] = gen_lowpart (SImode, operands[1]);
5293
5294 /* Handle a partial overlap. */
5295 if (rtx_equal_p (operands[0], operands[3]))
5296 {
5297 rtx tmp0 = operands[0];
5298 rtx tmp1 = operands[1];
5299
5300 operands[0] = operands[2];
5301 operands[1] = operands[3];
5302 operands[2] = tmp0;
5303 operands[3] = tmp1;
5304 }
5305 "
5306 )
5307
5308 ;; We can't actually do base+index doubleword loads if the index and
5309 ;; destination overlap. Split here so that we at least have chance to
5310 ;; schedule.
5311 (define_split
5312 [(set (match_operand:DI 0 "s_register_operand" "")
5313 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5314 (match_operand:SI 2 "s_register_operand" ""))))]
5315 "TARGET_LDRD
5316 && reg_overlap_mentioned_p (operands[0], operands[1])
5317 && reg_overlap_mentioned_p (operands[0], operands[2])"
5318 [(set (match_dup 4)
5319 (plus:SI (match_dup 1)
5320 (match_dup 2)))
5321 (set (match_dup 0)
5322 (mem:DI (match_dup 4)))]
5323 "
5324 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5325 "
5326 )
5327
5328 (define_expand "movsi"
5329 [(set (match_operand:SI 0 "general_operand")
5330 (match_operand:SI 1 "general_operand"))]
5331 "TARGET_EITHER"
5332 "
5333 {
5334 rtx base, offset, tmp;
5335
5336 gcc_checking_assert (aligned_operand (operands[0], SImode));
5337 gcc_checking_assert (aligned_operand (operands[1], SImode));
5338 if (TARGET_32BIT || TARGET_HAVE_MOVT)
5339 {
5340 /* Everything except mem = const or mem = mem can be done easily. */
5341 if (MEM_P (operands[0]))
5342 operands[1] = force_reg (SImode, operands[1]);
5343 if (arm_general_register_operand (operands[0], SImode)
5344 && CONST_INT_P (operands[1])
5345 && !(const_ok_for_arm (INTVAL (operands[1]))
5346 || const_ok_for_arm (~INTVAL (operands[1]))))
5347 {
5348 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5349 {
5350 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5351 DONE;
5352 }
5353 else
5354 {
5355 arm_split_constant (SET, SImode, NULL_RTX,
5356 INTVAL (operands[1]), operands[0], NULL_RTX,
5357 optimize && can_create_pseudo_p ());
5358 DONE;
5359 }
5360 }
5361 }
5362 else /* Target doesn't have MOVT... */
5363 {
5364 if (can_create_pseudo_p ())
5365 {
5366 if (!REG_P (operands[0]))
5367 operands[1] = force_reg (SImode, operands[1]);
5368 }
5369 }
5370
5371 split_const (operands[1], &base, &offset);
5372 if (INTVAL (offset) != 0
5373 && targetm.cannot_force_const_mem (SImode, operands[1]))
5374 {
5375 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5376 emit_move_insn (tmp, base);
5377 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5378 DONE;
5379 }
5380
5381 tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
5382
5383 /* Recognize the case where operand[1] is a reference to thread-local
5384 data and load its address to a register. Offsets have been split off
5385 already. */
5386 if (arm_tls_referenced_p (operands[1]))
5387 operands[1] = legitimize_tls_address (operands[1], tmp);
5388 else if (flag_pic
5389 && (CONSTANT_P (operands[1])
5390 || symbol_mentioned_p (operands[1])
5391 || label_mentioned_p (operands[1])))
5392 operands[1] =
5393 legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
5394 }
5395 "
5396 )
5397
5398 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5399 ;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5400 ;; so this does not matter.
5401 (define_insn "*arm_movt"
5402 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
5403 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
5404 (match_operand:SI 2 "general_operand" "i,i")))]
5405 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
5406 "@
5407 movt%?\t%0, #:upper16:%c2
5408 movt\t%0, #:upper16:%c2"
5409 [(set_attr "arch" "32,v8mb")
5410 (set_attr "predicable" "yes")
5411 (set_attr "length" "4")
5412 (set_attr "type" "alu_sreg")]
5413 )
5414
5415 (define_insn "*arm_movsi_insn"
5416 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5417 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
5418 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
5419 && ( register_operand (operands[0], SImode)
5420 || register_operand (operands[1], SImode))"
5421 "@
5422 mov%?\\t%0, %1
5423 mov%?\\t%0, %1
5424 mvn%?\\t%0, #%B1
5425 movw%?\\t%0, %1
5426 ldr%?\\t%0, %1
5427 str%?\\t%1, %0"
5428 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
5429 (set_attr "predicable" "yes")
5430 (set_attr "arch" "*,*,*,v6t2,*,*")
5431 (set_attr "pool_range" "*,*,*,*,4096,*")
5432 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5433 )
5434
5435 (define_split
5436 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5437 (match_operand:SI 1 "const_int_operand" ""))]
5438 "(TARGET_32BIT || TARGET_HAVE_MOVT)
5439 && (!(const_ok_for_arm (INTVAL (operands[1]))
5440 || const_ok_for_arm (~INTVAL (operands[1]))))"
5441 [(clobber (const_int 0))]
5442 "
5443 arm_split_constant (SET, SImode, NULL_RTX,
5444 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5445 DONE;
5446 "
5447 )
5448
5449 ;; A normal way to do (symbol + offset) requires three instructions at least
5450 ;; (depends on how big the offset is) as below:
5451 ;; movw r0, #:lower16:g
5452 ;; movw r0, #:upper16:g
5453 ;; adds r0, #4
5454 ;;
5455 ;; A better way would be:
5456 ;; movw r0, #:lower16:g+4
5457 ;; movw r0, #:upper16:g+4
5458 ;;
5459 ;; The limitation of this way is that the length of offset should be a 16-bit
5460 ;; signed value, because current assembler only supports REL type relocation for
5461 ;; such case. If the more powerful RELA type is supported in future, we should
5462 ;; update this pattern to go with better way.
5463 (define_split
5464 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5465 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5466 (match_operand:SI 2 "const_int_operand" ""))))]
5467 "TARGET_THUMB
5468 && TARGET_HAVE_MOVT
5469 && arm_disable_literal_pool
5470 && reload_completed
5471 && GET_CODE (operands[1]) == SYMBOL_REF"
5472 [(clobber (const_int 0))]
5473 "
5474 int offset = INTVAL (operands[2]);
5475
5476 if (offset < -0x8000 || offset > 0x7fff)
5477 {
5478 arm_emit_movpair (operands[0], operands[1]);
5479 emit_insn (gen_rtx_SET (operands[0],
5480 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5481 }
5482 else
5483 {
5484 rtx op = gen_rtx_CONST (SImode,
5485 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5486 arm_emit_movpair (operands[0], op);
5487 }
5488 "
5489 )
5490
5491 ;; Split symbol_refs at the later stage (after cprop), instead of generating
5492 ;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5493 ;; and lo_sum would be merged back into memory load at cprop. However,
5494 ;; if the default is to prefer movt/movw rather than a load from the constant
5495 ;; pool, the performance is better.
5496 (define_split
5497 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5498 (match_operand:SI 1 "general_operand" ""))]
5499 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5500 && !target_word_relocations
5501 && !arm_tls_referenced_p (operands[1])"
5502 [(clobber (const_int 0))]
5503 {
5504 arm_emit_movpair (operands[0], operands[1]);
5505 DONE;
5506 })
5507
5508 ;; When generating pic, we need to load the symbol offset into a register.
5509 ;; So that the optimizer does not confuse this with a normal symbol load
5510 ;; we use an unspec. The offset will be loaded from a constant pool entry,
5511 ;; since that is the only type of relocation we can use.
5512
5513 ;; Wrap calculation of the whole PIC address in a single pattern for the
5514 ;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5515 ;; a PIC address involves two loads from memory, so we want to CSE it
5516 ;; as often as possible.
5517 ;; This pattern will be split into one of the pic_load_addr_* patterns
5518 ;; and a move after GCSE optimizations.
5519 ;;
5520 ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5521 (define_expand "calculate_pic_address"
5522 [(set (match_operand:SI 0 "register_operand")
5523 (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
5524 (unspec:SI [(match_operand:SI 2 "" "")]
5525 UNSPEC_PIC_SYM))))]
5526 "flag_pic"
5527 )
5528
5529 ;; Split calculate_pic_address into pic_load_addr_* and a move.
5530 (define_split
5531 [(set (match_operand:SI 0 "register_operand" "")
5532 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5533 (unspec:SI [(match_operand:SI 2 "" "")]
5534 UNSPEC_PIC_SYM))))]
5535 "flag_pic"
5536 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5537 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5538 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5539 )
5540
5541 ;; operand1 is the memory address to go into
5542 ;; pic_load_addr_32bit.
5543 ;; operand2 is the PIC label to be emitted
5544 ;; from pic_add_dot_plus_eight.
5545 ;; We do this to allow hoisting of the entire insn.
5546 (define_insn_and_split "pic_load_addr_unified"
5547 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5548 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5549 (match_operand:SI 2 "" "")]
5550 UNSPEC_PIC_UNIFIED))]
5551 "flag_pic"
5552 "#"
5553 "&& reload_completed"
5554 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5555 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5556 (match_dup 2)] UNSPEC_PIC_BASE))]
5557 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5558 [(set_attr "type" "load_4,load_4,load_4")
5559 (set_attr "pool_range" "4096,4094,1022")
5560 (set_attr "neg_pool_range" "4084,0,0")
5561 (set_attr "arch" "a,t2,t1")
5562 (set_attr "length" "8,6,4")]
5563 )
5564
5565 ;; The rather odd constraints on the following are to force reload to leave
5566 ;; the insn alone, and to force the minipool generation pass to then move
5567 ;; the GOT symbol to memory.
5568
5569 (define_insn "pic_load_addr_32bit"
5570 [(set (match_operand:SI 0 "s_register_operand" "=r")
5571 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5572 "TARGET_32BIT && flag_pic"
5573 "ldr%?\\t%0, %1"
5574 [(set_attr "type" "load_4")
5575 (set (attr "pool_range")
5576 (if_then_else (eq_attr "is_thumb" "no")
5577 (const_int 4096)
5578 (const_int 4094)))
5579 (set (attr "neg_pool_range")
5580 (if_then_else (eq_attr "is_thumb" "no")
5581 (const_int 4084)
5582 (const_int 0)))]
5583 )
5584
5585 (define_insn "pic_load_addr_thumb1"
5586 [(set (match_operand:SI 0 "s_register_operand" "=l")
5587 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5588 "TARGET_THUMB1 && flag_pic"
5589 "ldr\\t%0, %1"
5590 [(set_attr "type" "load_4")
5591 (set (attr "pool_range") (const_int 1018))]
5592 )
5593
5594 (define_insn "pic_add_dot_plus_four"
5595 [(set (match_operand:SI 0 "register_operand" "=r")
5596 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5597 (const_int 4)
5598 (match_operand 2 "" "")]
5599 UNSPEC_PIC_BASE))]
5600 "TARGET_THUMB"
5601 "*
5602 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5603 INTVAL (operands[2]));
5604 return \"add\\t%0, %|pc\";
5605 "
5606 [(set_attr "length" "2")
5607 (set_attr "type" "alu_sreg")]
5608 )
5609
5610 (define_insn "pic_add_dot_plus_eight"
5611 [(set (match_operand:SI 0 "register_operand" "=r")
5612 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5613 (const_int 8)
5614 (match_operand 2 "" "")]
5615 UNSPEC_PIC_BASE))]
5616 "TARGET_ARM"
5617 "*
5618 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5619 INTVAL (operands[2]));
5620 return \"add%?\\t%0, %|pc, %1\";
5621 "
5622 [(set_attr "predicable" "yes")
5623 (set_attr "type" "alu_sreg")]
5624 )
5625
5626 (define_insn "tls_load_dot_plus_eight"
5627 [(set (match_operand:SI 0 "register_operand" "=r")
5628 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5629 (const_int 8)
5630 (match_operand 2 "" "")]
5631 UNSPEC_PIC_BASE)))]
5632 "TARGET_ARM"
5633 "*
5634 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5635 INTVAL (operands[2]));
5636 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5637 "
5638 [(set_attr "predicable" "yes")
5639 (set_attr "type" "load_4")]
5640 )
5641
5642 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5643 ;; followed by a load. These sequences can be crunched down to
5644 ;; tls_load_dot_plus_eight by a peephole.
5645
5646 (define_peephole2
5647 [(set (match_operand:SI 0 "register_operand" "")
5648 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5649 (const_int 8)
5650 (match_operand 1 "" "")]
5651 UNSPEC_PIC_BASE))
5652 (set (match_operand:SI 2 "arm_general_register_operand" "")
5653 (mem:SI (match_dup 0)))]
5654 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5655 [(set (match_dup 2)
5656 (mem:SI (unspec:SI [(match_dup 3)
5657 (const_int 8)
5658 (match_dup 1)]
5659 UNSPEC_PIC_BASE)))]
5660 ""
5661 )
5662
5663 (define_insn "pic_offset_arm"
5664 [(set (match_operand:SI 0 "register_operand" "=r")
5665 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5666 (unspec:SI [(match_operand:SI 2 "" "X")]
5667 UNSPEC_PIC_OFFSET))))]
5668 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5669 "ldr%?\\t%0, [%1,%2]"
5670 [(set_attr "type" "load_4")]
5671 )
5672
5673 (define_expand "builtin_setjmp_receiver"
5674 [(label_ref (match_operand 0 "" ""))]
5675 "flag_pic"
5676 "
5677 {
5678 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5679 register. */
5680 if (arm_pic_register != INVALID_REGNUM)
5681 arm_load_pic_register (1UL << 3, NULL_RTX);
5682 DONE;
5683 }")
5684
5685 ;; If copying one reg to another we can set the condition codes according to
5686 ;; its value. Such a move is common after a return from subroutine and the
5687 ;; result is being tested against zero.
5688
5689 (define_insn "*movsi_compare0"
5690 [(set (reg:CC CC_REGNUM)
5691 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5692 (const_int 0)))
5693 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5694 (match_dup 1))]
5695 "TARGET_32BIT"
5696 "@
5697 cmp%?\\t%0, #0
5698 subs%?\\t%0, %1, #0"
5699 [(set_attr "conds" "set")
5700 (set_attr "type" "alus_imm,alus_imm")]
5701 )
5702
5703 ;; Subroutine to store a half word from a register into memory.
5704 ;; Operand 0 is the source register (HImode)
5705 ;; Operand 1 is the destination address in a register (SImode)
5706
5707 ;; In both this routine and the next, we must be careful not to spill
5708 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5709 ;; can generate unrecognizable rtl.
5710
5711 (define_expand "storehi"
5712 [;; store the low byte
5713 (set (match_operand 1 "" "") (match_dup 3))
5714 ;; extract the high byte
5715 (set (match_dup 2)
5716 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5717 ;; store the high byte
5718 (set (match_dup 4) (match_dup 5))]
5719 "TARGET_ARM"
5720 "
5721 {
5722 rtx op1 = operands[1];
5723 rtx addr = XEXP (op1, 0);
5724 enum rtx_code code = GET_CODE (addr);
5725
5726 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5727 || code == MINUS)
5728 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5729
5730 operands[4] = adjust_address (op1, QImode, 1);
5731 operands[1] = adjust_address (operands[1], QImode, 0);
5732 operands[3] = gen_lowpart (QImode, operands[0]);
5733 operands[0] = gen_lowpart (SImode, operands[0]);
5734 operands[2] = gen_reg_rtx (SImode);
5735 operands[5] = gen_lowpart (QImode, operands[2]);
5736 }"
5737 )
5738
5739 (define_expand "storehi_bigend"
5740 [(set (match_dup 4) (match_dup 3))
5741 (set (match_dup 2)
5742 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5743 (set (match_operand 1 "" "") (match_dup 5))]
5744 "TARGET_ARM"
5745 "
5746 {
5747 rtx op1 = operands[1];
5748 rtx addr = XEXP (op1, 0);
5749 enum rtx_code code = GET_CODE (addr);
5750
5751 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5752 || code == MINUS)
5753 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5754
5755 operands[4] = adjust_address (op1, QImode, 1);
5756 operands[1] = adjust_address (operands[1], QImode, 0);
5757 operands[3] = gen_lowpart (QImode, operands[0]);
5758 operands[0] = gen_lowpart (SImode, operands[0]);
5759 operands[2] = gen_reg_rtx (SImode);
5760 operands[5] = gen_lowpart (QImode, operands[2]);
5761 }"
5762 )
5763
5764 ;; Subroutine to store a half word integer constant into memory.
5765 (define_expand "storeinthi"
5766 [(set (match_operand 0 "" "")
5767 (match_operand 1 "" ""))
5768 (set (match_dup 3) (match_dup 2))]
5769 "TARGET_ARM"
5770 "
5771 {
5772 HOST_WIDE_INT value = INTVAL (operands[1]);
5773 rtx addr = XEXP (operands[0], 0);
5774 rtx op0 = operands[0];
5775 enum rtx_code code = GET_CODE (addr);
5776
5777 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5778 || code == MINUS)
5779 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5780
5781 operands[1] = gen_reg_rtx (SImode);
5782 if (BYTES_BIG_ENDIAN)
5783 {
5784 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5785 if ((value & 255) == ((value >> 8) & 255))
5786 operands[2] = operands[1];
5787 else
5788 {
5789 operands[2] = gen_reg_rtx (SImode);
5790 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5791 }
5792 }
5793 else
5794 {
5795 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5796 if ((value & 255) == ((value >> 8) & 255))
5797 operands[2] = operands[1];
5798 else
5799 {
5800 operands[2] = gen_reg_rtx (SImode);
5801 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5802 }
5803 }
5804
5805 operands[3] = adjust_address (op0, QImode, 1);
5806 operands[0] = adjust_address (operands[0], QImode, 0);
5807 operands[2] = gen_lowpart (QImode, operands[2]);
5808 operands[1] = gen_lowpart (QImode, operands[1]);
5809 }"
5810 )
5811
5812 (define_expand "storehi_single_op"
5813 [(set (match_operand:HI 0 "memory_operand")
5814 (match_operand:HI 1 "general_operand"))]
5815 "TARGET_32BIT && arm_arch4"
5816 "
5817 if (!s_register_operand (operands[1], HImode))
5818 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5819 "
5820 )
5821
5822 (define_expand "movhi"
5823 [(set (match_operand:HI 0 "general_operand")
5824 (match_operand:HI 1 "general_operand"))]
5825 "TARGET_EITHER"
5826 "
5827 gcc_checking_assert (aligned_operand (operands[0], HImode));
5828 gcc_checking_assert (aligned_operand (operands[1], HImode));
5829 if (TARGET_ARM)
5830 {
5831 if (can_create_pseudo_p ())
5832 {
5833 if (MEM_P (operands[0]))
5834 {
5835 if (arm_arch4)
5836 {
5837 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5838 DONE;
5839 }
5840 if (CONST_INT_P (operands[1]))
5841 emit_insn (gen_storeinthi (operands[0], operands[1]));
5842 else
5843 {
5844 if (MEM_P (operands[1]))
5845 operands[1] = force_reg (HImode, operands[1]);
5846 if (BYTES_BIG_ENDIAN)
5847 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5848 else
5849 emit_insn (gen_storehi (operands[1], operands[0]));
5850 }
5851 DONE;
5852 }
5853 /* Sign extend a constant, and keep it in an SImode reg. */
5854 else if (CONST_INT_P (operands[1]))
5855 {
5856 rtx reg = gen_reg_rtx (SImode);
5857 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5858
5859 /* If the constant is already valid, leave it alone. */
5860 if (!const_ok_for_arm (val))
5861 {
5862 /* If setting all the top bits will make the constant
5863 loadable in a single instruction, then set them.
5864 Otherwise, sign extend the number. */
5865
5866 if (const_ok_for_arm (~(val | ~0xffff)))
5867 val |= ~0xffff;
5868 else if (val & 0x8000)
5869 val |= ~0xffff;
5870 }
5871
5872 emit_insn (gen_movsi (reg, GEN_INT (val)));
5873 operands[1] = gen_lowpart (HImode, reg);
5874 }
5875 else if (arm_arch4 && optimize && can_create_pseudo_p ()
5876 && MEM_P (operands[1]))
5877 {
5878 rtx reg = gen_reg_rtx (SImode);
5879
5880 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5881 operands[1] = gen_lowpart (HImode, reg);
5882 }
5883 else if (!arm_arch4)
5884 {
5885 if (MEM_P (operands[1]))
5886 {
5887 rtx base;
5888 rtx offset = const0_rtx;
5889 rtx reg = gen_reg_rtx (SImode);
5890
5891 if ((REG_P (base = XEXP (operands[1], 0))
5892 || (GET_CODE (base) == PLUS
5893 && (CONST_INT_P (offset = XEXP (base, 1)))
5894 && ((INTVAL(offset) & 1) != 1)
5895 && REG_P (base = XEXP (base, 0))))
5896 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5897 {
5898 rtx new_rtx;
5899
5900 new_rtx = widen_memory_access (operands[1], SImode,
5901 ((INTVAL (offset) & ~3)
5902 - INTVAL (offset)));
5903 emit_insn (gen_movsi (reg, new_rtx));
5904 if (((INTVAL (offset) & 2) != 0)
5905 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5906 {
5907 rtx reg2 = gen_reg_rtx (SImode);
5908
5909 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5910 reg = reg2;
5911 }
5912 }
5913 else
5914 emit_insn (gen_movhi_bytes (reg, operands[1]));
5915
5916 operands[1] = gen_lowpart (HImode, reg);
5917 }
5918 }
5919 }
5920 /* Handle loading a large integer during reload. */
5921 else if (CONST_INT_P (operands[1])
5922 && !const_ok_for_arm (INTVAL (operands[1]))
5923 && !const_ok_for_arm (~INTVAL (operands[1])))
5924 {
5925 /* Writing a constant to memory needs a scratch, which should
5926 be handled with SECONDARY_RELOADs. */
5927 gcc_assert (REG_P (operands[0]));
5928
5929 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5930 emit_insn (gen_movsi (operands[0], operands[1]));
5931 DONE;
5932 }
5933 }
5934 else if (TARGET_THUMB2)
5935 {
5936 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
5937 if (can_create_pseudo_p ())
5938 {
5939 if (!REG_P (operands[0]))
5940 operands[1] = force_reg (HImode, operands[1]);
5941 /* Zero extend a constant, and keep it in an SImode reg. */
5942 else if (CONST_INT_P (operands[1]))
5943 {
5944 rtx reg = gen_reg_rtx (SImode);
5945 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5946
5947 emit_insn (gen_movsi (reg, GEN_INT (val)));
5948 operands[1] = gen_lowpart (HImode, reg);
5949 }
5950 }
5951 }
5952 else /* TARGET_THUMB1 */
5953 {
5954 if (can_create_pseudo_p ())
5955 {
5956 if (CONST_INT_P (operands[1]))
5957 {
5958 rtx reg = gen_reg_rtx (SImode);
5959
5960 emit_insn (gen_movsi (reg, operands[1]));
5961 operands[1] = gen_lowpart (HImode, reg);
5962 }
5963
5964 /* ??? We shouldn't really get invalid addresses here, but this can
5965 happen if we are passed a SP (never OK for HImode/QImode) or
5966 virtual register (also rejected as illegitimate for HImode/QImode)
5967 relative address. */
5968 /* ??? This should perhaps be fixed elsewhere, for instance, in
5969 fixup_stack_1, by checking for other kinds of invalid addresses,
5970 e.g. a bare reference to a virtual register. This may confuse the
5971 alpha though, which must handle this case differently. */
5972 if (MEM_P (operands[0])
5973 && !memory_address_p (GET_MODE (operands[0]),
5974 XEXP (operands[0], 0)))
5975 operands[0]
5976 = replace_equiv_address (operands[0],
5977 copy_to_reg (XEXP (operands[0], 0)));
5978
5979 if (MEM_P (operands[1])
5980 && !memory_address_p (GET_MODE (operands[1]),
5981 XEXP (operands[1], 0)))
5982 operands[1]
5983 = replace_equiv_address (operands[1],
5984 copy_to_reg (XEXP (operands[1], 0)));
5985
5986 if (MEM_P (operands[1]) && optimize > 0)
5987 {
5988 rtx reg = gen_reg_rtx (SImode);
5989
5990 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5991 operands[1] = gen_lowpart (HImode, reg);
5992 }
5993
5994 if (MEM_P (operands[0]))
5995 operands[1] = force_reg (HImode, operands[1]);
5996 }
5997 else if (CONST_INT_P (operands[1])
5998 && !satisfies_constraint_I (operands[1]))
5999 {
6000 /* Handle loading a large integer during reload. */
6001
6002 /* Writing a constant to memory needs a scratch, which should
6003 be handled with SECONDARY_RELOADs. */
6004 gcc_assert (REG_P (operands[0]));
6005
6006 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6007 emit_insn (gen_movsi (operands[0], operands[1]));
6008 DONE;
6009 }
6010 }
6011 "
6012 )
6013
6014 (define_expand "movhi_bytes"
6015 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6016 (set (match_dup 3)
6017 (zero_extend:SI (match_dup 6)))
6018 (set (match_operand:SI 0 "" "")
6019 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6020 "TARGET_ARM"
6021 "
6022 {
6023 rtx mem1, mem2;
6024 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6025
6026 mem1 = change_address (operands[1], QImode, addr);
6027 mem2 = change_address (operands[1], QImode,
6028 plus_constant (Pmode, addr, 1));
6029 operands[0] = gen_lowpart (SImode, operands[0]);
6030 operands[1] = mem1;
6031 operands[2] = gen_reg_rtx (SImode);
6032 operands[3] = gen_reg_rtx (SImode);
6033 operands[6] = mem2;
6034
6035 if (BYTES_BIG_ENDIAN)
6036 {
6037 operands[4] = operands[2];
6038 operands[5] = operands[3];
6039 }
6040 else
6041 {
6042 operands[4] = operands[3];
6043 operands[5] = operands[2];
6044 }
6045 }"
6046 )
6047
6048 (define_expand "movhi_bigend"
6049 [(set (match_dup 2)
6050 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
6051 (const_int 16)))
6052 (set (match_dup 3)
6053 (ashiftrt:SI (match_dup 2) (const_int 16)))
6054 (set (match_operand:HI 0 "s_register_operand")
6055 (match_dup 4))]
6056 "TARGET_ARM"
6057 "
6058 operands[2] = gen_reg_rtx (SImode);
6059 operands[3] = gen_reg_rtx (SImode);
6060 operands[4] = gen_lowpart (HImode, operands[3]);
6061 "
6062 )
6063
6064 ;; Pattern to recognize insn generated default case above
6065 (define_insn "*movhi_insn_arch4"
6066 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6067 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
6068 "TARGET_ARM
6069 && arm_arch4 && !TARGET_HARD_FLOAT
6070 && (register_operand (operands[0], HImode)
6071 || register_operand (operands[1], HImode))"
6072 "@
6073 mov%?\\t%0, %1\\t%@ movhi
6074 mvn%?\\t%0, #%B1\\t%@ movhi
6075 movw%?\\t%0, %L1\\t%@ movhi
6076 strh%?\\t%1, %0\\t%@ movhi
6077 ldrh%?\\t%0, %1\\t%@ movhi"
6078 [(set_attr "predicable" "yes")
6079 (set_attr "pool_range" "*,*,*,*,256")
6080 (set_attr "neg_pool_range" "*,*,*,*,244")
6081 (set_attr "arch" "*,*,v6t2,*,*")
6082 (set_attr_alternative "type"
6083 [(if_then_else (match_operand 1 "const_int_operand" "")
6084 (const_string "mov_imm" )
6085 (const_string "mov_reg"))
6086 (const_string "mvn_imm")
6087 (const_string "mov_imm")
6088 (const_string "store_4")
6089 (const_string "load_4")])]
6090 )
6091
6092 (define_insn "*movhi_bytes"
6093 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
6094 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
6095 "TARGET_ARM && !TARGET_HARD_FLOAT"
6096 "@
6097 mov%?\\t%0, %1\\t%@ movhi
6098 mov%?\\t%0, %1\\t%@ movhi
6099 mvn%?\\t%0, #%B1\\t%@ movhi"
6100 [(set_attr "predicable" "yes")
6101 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
6102 )
6103
6104 ;; We use a DImode scratch because we may occasionally need an additional
6105 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
6106 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
6107 ;; The reload_in<m> and reload_out<m> patterns require special constraints
6108 ;; to be correctly handled in default_secondary_reload function.
6109 (define_expand "reload_outhi"
6110 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6111 (match_operand:HI 1 "s_register_operand" "r")
6112 (match_operand:DI 2 "s_register_operand" "=&l")])]
6113 "TARGET_EITHER"
6114 "if (TARGET_ARM)
6115 arm_reload_out_hi (operands);
6116 else
6117 thumb_reload_out_hi (operands);
6118 DONE;
6119 "
6120 )
6121
6122 (define_expand "reload_inhi"
6123 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6124 (match_operand:HI 1 "arm_reload_memory_operand" "o")
6125 (match_operand:DI 2 "s_register_operand" "=&r")])]
6126 "TARGET_EITHER"
6127 "
6128 if (TARGET_ARM)
6129 arm_reload_in_hi (operands);
6130 else
6131 thumb_reload_out_hi (operands);
6132 DONE;
6133 ")
6134
6135 (define_expand "movqi"
6136 [(set (match_operand:QI 0 "general_operand")
6137 (match_operand:QI 1 "general_operand"))]
6138 "TARGET_EITHER"
6139 "
6140 /* Everything except mem = const or mem = mem can be done easily */
6141
6142 if (can_create_pseudo_p ())
6143 {
6144 if (CONST_INT_P (operands[1]))
6145 {
6146 rtx reg = gen_reg_rtx (SImode);
6147
6148 /* For thumb we want an unsigned immediate, then we are more likely
6149 to be able to use a movs insn. */
6150 if (TARGET_THUMB)
6151 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6152
6153 emit_insn (gen_movsi (reg, operands[1]));
6154 operands[1] = gen_lowpart (QImode, reg);
6155 }
6156
6157 if (TARGET_THUMB)
6158 {
6159 /* ??? We shouldn't really get invalid addresses here, but this can
6160 happen if we are passed a SP (never OK for HImode/QImode) or
6161 virtual register (also rejected as illegitimate for HImode/QImode)
6162 relative address. */
6163 /* ??? This should perhaps be fixed elsewhere, for instance, in
6164 fixup_stack_1, by checking for other kinds of invalid addresses,
6165 e.g. a bare reference to a virtual register. This may confuse the
6166 alpha though, which must handle this case differently. */
6167 if (MEM_P (operands[0])
6168 && !memory_address_p (GET_MODE (operands[0]),
6169 XEXP (operands[0], 0)))
6170 operands[0]
6171 = replace_equiv_address (operands[0],
6172 copy_to_reg (XEXP (operands[0], 0)));
6173 if (MEM_P (operands[1])
6174 && !memory_address_p (GET_MODE (operands[1]),
6175 XEXP (operands[1], 0)))
6176 operands[1]
6177 = replace_equiv_address (operands[1],
6178 copy_to_reg (XEXP (operands[1], 0)));
6179 }
6180
6181 if (MEM_P (operands[1]) && optimize > 0)
6182 {
6183 rtx reg = gen_reg_rtx (SImode);
6184
6185 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6186 operands[1] = gen_lowpart (QImode, reg);
6187 }
6188
6189 if (MEM_P (operands[0]))
6190 operands[1] = force_reg (QImode, operands[1]);
6191 }
6192 else if (TARGET_THUMB
6193 && CONST_INT_P (operands[1])
6194 && !satisfies_constraint_I (operands[1]))
6195 {
6196 /* Handle loading a large integer during reload. */
6197
6198 /* Writing a constant to memory needs a scratch, which should
6199 be handled with SECONDARY_RELOADs. */
6200 gcc_assert (REG_P (operands[0]));
6201
6202 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6203 emit_insn (gen_movsi (operands[0], operands[1]));
6204 DONE;
6205 }
6206 "
6207 )
6208
6209 (define_insn "*arm_movqi_insn"
6210 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
6211 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
6212 "TARGET_32BIT
6213 && ( register_operand (operands[0], QImode)
6214 || register_operand (operands[1], QImode))"
6215 "@
6216 mov%?\\t%0, %1
6217 mov%?\\t%0, %1
6218 mov%?\\t%0, %1
6219 mov%?\\t%0, %1
6220 mvn%?\\t%0, #%B1
6221 ldrb%?\\t%0, %1
6222 strb%?\\t%1, %0
6223 ldrb%?\\t%0, %1
6224 strb%?\\t%1, %0"
6225 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
6226 (set_attr "predicable" "yes")
6227 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
6228 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6229 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
6230 )
6231
6232 ;; HFmode moves
6233 (define_expand "movhf"
6234 [(set (match_operand:HF 0 "general_operand")
6235 (match_operand:HF 1 "general_operand"))]
6236 "TARGET_EITHER"
6237 "
6238 gcc_checking_assert (aligned_operand (operands[0], HFmode));
6239 gcc_checking_assert (aligned_operand (operands[1], HFmode));
6240 if (TARGET_32BIT)
6241 {
6242 if (MEM_P (operands[0]))
6243 operands[1] = force_reg (HFmode, operands[1]);
6244 }
6245 else /* TARGET_THUMB1 */
6246 {
6247 if (can_create_pseudo_p ())
6248 {
6249 if (!REG_P (operands[0]))
6250 operands[1] = force_reg (HFmode, operands[1]);
6251 }
6252 }
6253 "
6254 )
6255
6256 (define_insn "*arm32_movhf"
6257 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6258 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6259 "TARGET_32BIT && !TARGET_HARD_FLOAT
6260 && ( s_register_operand (operands[0], HFmode)
6261 || s_register_operand (operands[1], HFmode))"
6262 "*
6263 switch (which_alternative)
6264 {
6265 case 0: /* ARM register from memory */
6266 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
6267 case 1: /* memory from ARM register */
6268 return \"strh%?\\t%1, %0\\t%@ __fp16\";
6269 case 2: /* ARM register from ARM register */
6270 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6271 case 3: /* ARM register from constant */
6272 {
6273 long bits;
6274 rtx ops[4];
6275
6276 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6277 HFmode);
6278 ops[0] = operands[0];
6279 ops[1] = GEN_INT (bits);
6280 ops[2] = GEN_INT (bits & 0xff00);
6281 ops[3] = GEN_INT (bits & 0x00ff);
6282
6283 if (arm_arch_thumb2)
6284 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6285 else
6286 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6287 return \"\";
6288 }
6289 default:
6290 gcc_unreachable ();
6291 }
6292 "
6293 [(set_attr "conds" "unconditional")
6294 (set_attr "type" "load_4,store_4,mov_reg,multiple")
6295 (set_attr "length" "4,4,4,8")
6296 (set_attr "predicable" "yes")]
6297 )
6298
6299 (define_expand "movsf"
6300 [(set (match_operand:SF 0 "general_operand")
6301 (match_operand:SF 1 "general_operand"))]
6302 "TARGET_EITHER"
6303 "
6304 gcc_checking_assert (aligned_operand (operands[0], SFmode));
6305 gcc_checking_assert (aligned_operand (operands[1], SFmode));
6306 if (TARGET_32BIT)
6307 {
6308 if (MEM_P (operands[0]))
6309 operands[1] = force_reg (SFmode, operands[1]);
6310 }
6311 else /* TARGET_THUMB1 */
6312 {
6313 if (can_create_pseudo_p ())
6314 {
6315 if (!REG_P (operands[0]))
6316 operands[1] = force_reg (SFmode, operands[1]);
6317 }
6318 }
6319
6320 /* Cannot load it directly, generate a load with clobber so that it can be
6321 loaded via GPR with MOV / MOVT. */
6322 if (arm_disable_literal_pool
6323 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6324 && CONST_DOUBLE_P (operands[1])
6325 && TARGET_HARD_FLOAT
6326 && !vfp3_const_double_rtx (operands[1]))
6327 {
6328 rtx clobreg = gen_reg_rtx (SFmode);
6329 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6330 clobreg));
6331 DONE;
6332 }
6333 "
6334 )
6335
6336 ;; Transform a floating-point move of a constant into a core register into
6337 ;; an SImode operation.
6338 (define_split
6339 [(set (match_operand:SF 0 "arm_general_register_operand" "")
6340 (match_operand:SF 1 "immediate_operand" ""))]
6341 "TARGET_EITHER
6342 && reload_completed
6343 && CONST_DOUBLE_P (operands[1])"
6344 [(set (match_dup 2) (match_dup 3))]
6345 "
6346 operands[2] = gen_lowpart (SImode, operands[0]);
6347 operands[3] = gen_lowpart (SImode, operands[1]);
6348 if (operands[2] == 0 || operands[3] == 0)
6349 FAIL;
6350 "
6351 )
6352
6353 (define_insn "*arm_movsf_soft_insn"
6354 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6355 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6356 "TARGET_32BIT
6357 && TARGET_SOFT_FLOAT
6358 && (!MEM_P (operands[0])
6359 || register_operand (operands[1], SFmode))"
6360 {
6361 switch (which_alternative)
6362 {
6363 case 0: return \"mov%?\\t%0, %1\";
6364 case 1:
6365 /* Cannot load it directly, split to load it via MOV / MOVT. */
6366 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6367 return \"#\";
6368 return \"ldr%?\\t%0, %1\\t%@ float\";
6369 case 2: return \"str%?\\t%1, %0\\t%@ float\";
6370 default: gcc_unreachable ();
6371 }
6372 }
6373 [(set_attr "predicable" "yes")
6374 (set_attr "type" "mov_reg,load_4,store_4")
6375 (set_attr "arm_pool_range" "*,4096,*")
6376 (set_attr "thumb2_pool_range" "*,4094,*")
6377 (set_attr "arm_neg_pool_range" "*,4084,*")
6378 (set_attr "thumb2_neg_pool_range" "*,0,*")]
6379 )
6380
6381 ;; Splitter for the above.
6382 (define_split
6383 [(set (match_operand:SF 0 "s_register_operand")
6384 (match_operand:SF 1 "const_double_operand"))]
6385 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6386 [(const_int 0)]
6387 {
6388 long buf;
6389 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
6390 rtx cst = gen_int_mode (buf, SImode);
6391 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
6392 DONE;
6393 }
6394 )
6395
6396 (define_expand "movdf"
6397 [(set (match_operand:DF 0 "general_operand")
6398 (match_operand:DF 1 "general_operand"))]
6399 "TARGET_EITHER"
6400 "
6401 gcc_checking_assert (aligned_operand (operands[0], DFmode));
6402 gcc_checking_assert (aligned_operand (operands[1], DFmode));
6403 if (TARGET_32BIT)
6404 {
6405 if (MEM_P (operands[0]))
6406 operands[1] = force_reg (DFmode, operands[1]);
6407 }
6408 else /* TARGET_THUMB */
6409 {
6410 if (can_create_pseudo_p ())
6411 {
6412 if (!REG_P (operands[0]))
6413 operands[1] = force_reg (DFmode, operands[1]);
6414 }
6415 }
6416
6417 /* Cannot load it directly, generate a load with clobber so that it can be
6418 loaded via GPR with MOV / MOVT. */
6419 if (arm_disable_literal_pool
6420 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6421 && CONSTANT_P (operands[1])
6422 && TARGET_HARD_FLOAT
6423 && !arm_const_double_rtx (operands[1])
6424 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
6425 {
6426 rtx clobreg = gen_reg_rtx (DFmode);
6427 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
6428 clobreg));
6429 DONE;
6430 }
6431 "
6432 )
6433
6434 ;; Reloading a df mode value stored in integer regs to memory can require a
6435 ;; scratch reg.
6436 ;; Another reload_out<m> pattern that requires special constraints.
6437 (define_expand "reload_outdf"
6438 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6439 (match_operand:DF 1 "s_register_operand" "r")
6440 (match_operand:SI 2 "s_register_operand" "=&r")]
6441 "TARGET_THUMB2"
6442 "
6443 {
6444 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6445
6446 if (code == REG)
6447 operands[2] = XEXP (operands[0], 0);
6448 else if (code == POST_INC || code == PRE_DEC)
6449 {
6450 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6451 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6452 emit_insn (gen_movdi (operands[0], operands[1]));
6453 DONE;
6454 }
6455 else if (code == PRE_INC)
6456 {
6457 rtx reg = XEXP (XEXP (operands[0], 0), 0);
6458
6459 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6460 operands[2] = reg;
6461 }
6462 else if (code == POST_DEC)
6463 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6464 else
6465 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6466 XEXP (XEXP (operands[0], 0), 1)));
6467
6468 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
6469 operands[1]));
6470
6471 if (code == POST_DEC)
6472 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6473
6474 DONE;
6475 }"
6476 )
6477
6478 (define_insn "*movdf_soft_insn"
6479 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6480 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6481 "TARGET_32BIT && TARGET_SOFT_FLOAT
6482 && ( register_operand (operands[0], DFmode)
6483 || register_operand (operands[1], DFmode))"
6484 "*
6485 switch (which_alternative)
6486 {
6487 case 0:
6488 case 1:
6489 case 2:
6490 return \"#\";
6491 case 3:
6492 /* Cannot load it directly, split to load it via MOV / MOVT. */
6493 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6494 return \"#\";
6495 /* Fall through. */
6496 default:
6497 return output_move_double (operands, true, NULL);
6498 }
6499 "
6500 [(set_attr "length" "8,12,16,8,8")
6501 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
6502 (set_attr "arm_pool_range" "*,*,*,1020,*")
6503 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
6504 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
6505 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
6506 )
6507
6508 ;; Splitter for the above.
6509 (define_split
6510 [(set (match_operand:DF 0 "s_register_operand")
6511 (match_operand:DF 1 "const_double_operand"))]
6512 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6513 [(const_int 0)]
6514 {
6515 long buf[2];
6516 int order = BYTES_BIG_ENDIAN ? 1 : 0;
6517 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
6518 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
6519 ival |= (zext_hwi (buf[1 - order], 32) << 32);
6520 rtx cst = gen_int_mode (ival, DImode);
6521 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
6522 DONE;
6523 }
6524 )
6525 \f
6526
6527 ;; load- and store-multiple insns
6528 ;; The arm can load/store any set of registers, provided that they are in
6529 ;; ascending order, but these expanders assume a contiguous set.
6530
6531 (define_expand "load_multiple"
6532 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6533 (match_operand:SI 1 "" ""))
6534 (use (match_operand:SI 2 "" ""))])]
6535 "TARGET_32BIT"
6536 {
6537 HOST_WIDE_INT offset = 0;
6538
6539 /* Support only fixed point registers. */
6540 if (!CONST_INT_P (operands[2])
6541 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
6542 || INTVAL (operands[2]) < 2
6543 || !MEM_P (operands[1])
6544 || !REG_P (operands[0])
6545 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6546 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6547 FAIL;
6548
6549 operands[3]
6550 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6551 INTVAL (operands[2]),
6552 force_reg (SImode, XEXP (operands[1], 0)),
6553 FALSE, operands[1], &offset);
6554 })
6555
6556 (define_expand "store_multiple"
6557 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6558 (match_operand:SI 1 "" ""))
6559 (use (match_operand:SI 2 "" ""))])]
6560 "TARGET_32BIT"
6561 {
6562 HOST_WIDE_INT offset = 0;
6563
6564 /* Support only fixed point registers. */
6565 if (!CONST_INT_P (operands[2])
6566 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
6567 || INTVAL (operands[2]) < 2
6568 || !REG_P (operands[1])
6569 || !MEM_P (operands[0])
6570 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6571 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6572 FAIL;
6573
6574 operands[3]
6575 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6576 INTVAL (operands[2]),
6577 force_reg (SImode, XEXP (operands[0], 0)),
6578 FALSE, operands[0], &offset);
6579 })
6580
6581
6582 (define_expand "setmemsi"
6583 [(match_operand:BLK 0 "general_operand")
6584 (match_operand:SI 1 "const_int_operand")
6585 (match_operand:SI 2 "const_int_operand")
6586 (match_operand:SI 3 "const_int_operand")]
6587 "TARGET_32BIT"
6588 {
6589 if (arm_gen_setmem (operands))
6590 DONE;
6591
6592 FAIL;
6593 })
6594
6595
6596 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6597 ;; We could let this apply for blocks of less than this, but it clobbers so
6598 ;; many registers that there is then probably a better way.
6599
6600 (define_expand "cpymemqi"
6601 [(match_operand:BLK 0 "general_operand")
6602 (match_operand:BLK 1 "general_operand")
6603 (match_operand:SI 2 "const_int_operand")
6604 (match_operand:SI 3 "const_int_operand")]
6605 ""
6606 "
6607 if (TARGET_32BIT)
6608 {
6609 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6610 && !optimize_function_for_size_p (cfun))
6611 {
6612 if (gen_cpymem_ldrd_strd (operands))
6613 DONE;
6614 FAIL;
6615 }
6616
6617 if (arm_gen_cpymemqi (operands))
6618 DONE;
6619 FAIL;
6620 }
6621 else /* TARGET_THUMB1 */
6622 {
6623 if ( INTVAL (operands[3]) != 4
6624 || INTVAL (operands[2]) > 48)
6625 FAIL;
6626
6627 thumb_expand_cpymemqi (operands);
6628 DONE;
6629 }
6630 "
6631 )
6632 \f
6633
6634 ;; Compare & branch insns
6635 ;; The range calculations are based as follows:
6636 ;; For forward branches, the address calculation returns the address of
6637 ;; the next instruction. This is 2 beyond the branch instruction.
6638 ;; For backward branches, the address calculation returns the address of
6639 ;; the first instruction in this pattern (cmp). This is 2 before the branch
6640 ;; instruction for the shortest sequence, and 4 before the branch instruction
6641 ;; if we have to jump around an unconditional branch.
6642 ;; To the basic branch range the PC offset must be added (this is +4).
6643 ;; So for forward branches we have
6644 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6645 ;; And for backward branches we have
6646 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6647 ;;
6648 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6649 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
6650
6651 (define_expand "cbranchsi4"
6652 [(set (pc) (if_then_else
6653 (match_operator 0 "expandable_comparison_operator"
6654 [(match_operand:SI 1 "s_register_operand")
6655 (match_operand:SI 2 "nonmemory_operand")])
6656 (label_ref (match_operand 3 "" ""))
6657 (pc)))]
6658 "TARGET_EITHER"
6659 "
6660 if (!TARGET_THUMB1)
6661 {
6662 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6663 FAIL;
6664 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6665 operands[3]));
6666 DONE;
6667 }
6668 if (thumb1_cmpneg_operand (operands[2], SImode))
6669 {
6670 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6671 operands[3], operands[0]));
6672 DONE;
6673 }
6674 if (!thumb1_cmp_operand (operands[2], SImode))
6675 operands[2] = force_reg (SImode, operands[2]);
6676 ")
6677
6678 (define_expand "cbranchsf4"
6679 [(set (pc) (if_then_else
6680 (match_operator 0 "expandable_comparison_operator"
6681 [(match_operand:SF 1 "s_register_operand")
6682 (match_operand:SF 2 "vfp_compare_operand")])
6683 (label_ref (match_operand 3 "" ""))
6684 (pc)))]
6685 "TARGET_32BIT && TARGET_HARD_FLOAT"
6686 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6687 operands[3])); DONE;"
6688 )
6689
6690 (define_expand "cbranchdf4"
6691 [(set (pc) (if_then_else
6692 (match_operator 0 "expandable_comparison_operator"
6693 [(match_operand:DF 1 "s_register_operand")
6694 (match_operand:DF 2 "vfp_compare_operand")])
6695 (label_ref (match_operand 3 "" ""))
6696 (pc)))]
6697 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6698 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6699 operands[3])); DONE;"
6700 )
6701
6702 (define_expand "cbranchdi4"
6703 [(set (pc) (if_then_else
6704 (match_operator 0 "expandable_comparison_operator"
6705 [(match_operand:DI 1 "s_register_operand")
6706 (match_operand:DI 2 "cmpdi_operand")])
6707 (label_ref (match_operand 3 "" ""))
6708 (pc)))]
6709 "TARGET_32BIT"
6710 "{
6711 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6712 FAIL;
6713 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6714 operands[3]));
6715 DONE;
6716 }"
6717 )
6718
6719 ;; Comparison and test insns
6720
6721 (define_insn "*arm_cmpsi_insn"
6722 [(set (reg:CC CC_REGNUM)
6723 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6724 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
6725 "TARGET_32BIT"
6726 "@
6727 cmp%?\\t%0, %1
6728 cmp%?\\t%0, %1
6729 cmp%?\\t%0, %1
6730 cmp%?\\t%0, %1
6731 cmn%?\\t%0, #%n1"
6732 [(set_attr "conds" "set")
6733 (set_attr "arch" "t2,t2,any,any,any")
6734 (set_attr "length" "2,2,4,4,4")
6735 (set_attr "predicable" "yes")
6736 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
6737 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
6738 )
6739
6740 (define_insn "*cmpsi_shiftsi"
6741 [(set (reg:CC CC_REGNUM)
6742 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
6743 (match_operator:SI 3 "shift_operator"
6744 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6745 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
6746 "TARGET_32BIT"
6747 "cmp\\t%0, %1%S3"
6748 [(set_attr "conds" "set")
6749 (set_attr "shift" "1")
6750 (set_attr "arch" "32,a,a")
6751 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
6752
6753 (define_insn "*cmpsi_shiftsi_swp"
6754 [(set (reg:CC_SWP CC_REGNUM)
6755 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6756 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6757 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6758 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
6759 "TARGET_32BIT"
6760 "cmp%?\\t%0, %1%S3"
6761 [(set_attr "conds" "set")
6762 (set_attr "shift" "1")
6763 (set_attr "arch" "32,a,a")
6764 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
6765
6766 (define_insn "*arm_cmpsi_negshiftsi_si"
6767 [(set (reg:CC_Z CC_REGNUM)
6768 (compare:CC_Z
6769 (neg:SI (match_operator:SI 1 "shift_operator"
6770 [(match_operand:SI 2 "s_register_operand" "r")
6771 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6772 (match_operand:SI 0 "s_register_operand" "r")))]
6773 "TARGET_ARM"
6774 "cmn%?\\t%0, %2%S1"
6775 [(set_attr "conds" "set")
6776 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6777 (const_string "alus_shift_imm")
6778 (const_string "alus_shift_reg")))
6779 (set_attr "predicable" "yes")]
6780 )
6781
6782 ;; DImode comparisons. The generic code generates branches that
6783 ;; if-conversion cannot reduce to a conditional compare, so we do
6784 ;; that directly.
6785
6786 (define_insn_and_split "*arm_cmpdi_insn"
6787 [(set (reg:CC_NCV CC_REGNUM)
6788 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
6789 (match_operand:DI 1 "arm_di_operand" "rDi")))
6790 (clobber (match_scratch:SI 2 "=r"))]
6791 "TARGET_32BIT"
6792 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
6793 "&& reload_completed"
6794 [(set (reg:CC CC_REGNUM)
6795 (compare:CC (match_dup 0) (match_dup 1)))
6796 (parallel [(set (reg:CC CC_REGNUM)
6797 (compare:CC (match_dup 3) (match_dup 4)))
6798 (set (match_dup 2)
6799 (minus:SI (match_dup 5)
6800 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
6801 {
6802 operands[3] = gen_highpart (SImode, operands[0]);
6803 operands[0] = gen_lowpart (SImode, operands[0]);
6804 if (CONST_INT_P (operands[1]))
6805 {
6806 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);
6807 if (operands[4] == const0_rtx)
6808 operands[5] = operands[3];
6809 else
6810 operands[5] = gen_rtx_PLUS (SImode, operands[3],
6811 gen_int_mode (-UINTVAL (operands[4]),
6812 SImode));
6813 }
6814 else
6815 {
6816 operands[4] = gen_highpart (SImode, operands[1]);
6817 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
6818 }
6819 operands[1] = gen_lowpart (SImode, operands[1]);
6820 operands[2] = gen_lowpart (SImode, operands[2]);
6821 }
6822 [(set_attr "conds" "set")
6823 (set_attr "length" "8")
6824 (set_attr "type" "multiple")]
6825 )
6826
6827 (define_insn_and_split "*arm_cmpdi_unsigned"
6828 [(set (reg:CC_CZ CC_REGNUM)
6829 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
6830 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
6831
6832 "TARGET_32BIT"
6833 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
6834 "&& reload_completed"
6835 [(set (reg:CC CC_REGNUM)
6836 (compare:CC (match_dup 2) (match_dup 3)))
6837 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
6838 (set (reg:CC CC_REGNUM)
6839 (compare:CC (match_dup 0) (match_dup 1))))]
6840 {
6841 operands[2] = gen_highpart (SImode, operands[0]);
6842 operands[0] = gen_lowpart (SImode, operands[0]);
6843 if (CONST_INT_P (operands[1]))
6844 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6845 else
6846 operands[3] = gen_highpart (SImode, operands[1]);
6847 operands[1] = gen_lowpart (SImode, operands[1]);
6848 }
6849 [(set_attr "conds" "set")
6850 (set_attr "enabled_for_short_it" "yes,yes,no,*")
6851 (set_attr "arch" "t2,t2,t2,a")
6852 (set_attr "length" "6,6,10,8")
6853 (set_attr "type" "multiple")]
6854 )
6855
6856 (define_insn "*arm_cmpdi_zero"
6857 [(set (reg:CC_Z CC_REGNUM)
6858 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
6859 (const_int 0)))
6860 (clobber (match_scratch:SI 1 "=r"))]
6861 "TARGET_32BIT"
6862 "orrs%?\\t%1, %Q0, %R0"
6863 [(set_attr "conds" "set")
6864 (set_attr "type" "logics_reg")]
6865 )
6866
6867 ; This insn allows redundant compares to be removed by cse, nothing should
6868 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6869 ; is deleted later on. The match_dup will match the mode here, so that
6870 ; mode changes of the condition codes aren't lost by this even though we don't
6871 ; specify what they are.
6872
6873 (define_insn "*deleted_compare"
6874 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6875 "TARGET_32BIT"
6876 "\\t%@ deleted compare"
6877 [(set_attr "conds" "set")
6878 (set_attr "length" "0")
6879 (set_attr "type" "no_insn")]
6880 )
6881
6882 \f
6883 ;; Conditional branch insns
6884
6885 (define_expand "cbranch_cc"
6886 [(set (pc)
6887 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
6888 (match_operand 2 "" "")])
6889 (label_ref (match_operand 3 "" ""))
6890 (pc)))]
6891 "TARGET_32BIT"
6892 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
6893 operands[1], operands[2], NULL_RTX);
6894 operands[2] = const0_rtx;"
6895 )
6896
6897 ;;
6898 ;; Patterns to match conditional branch insns.
6899 ;;
6900
6901 (define_insn "arm_cond_branch"
6902 [(set (pc)
6903 (if_then_else (match_operator 1 "arm_comparison_operator"
6904 [(match_operand 2 "cc_register" "") (const_int 0)])
6905 (label_ref (match_operand 0 "" ""))
6906 (pc)))]
6907 "TARGET_32BIT"
6908 "*
6909 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6910 {
6911 arm_ccfsm_state += 2;
6912 return \"\";
6913 }
6914 return \"b%d1\\t%l0\";
6915 "
6916 [(set_attr "conds" "use")
6917 (set_attr "type" "branch")
6918 (set (attr "length")
6919 (if_then_else
6920 (and (match_test "TARGET_THUMB2")
6921 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6922 (le (minus (match_dup 0) (pc)) (const_int 256))))
6923 (const_int 2)
6924 (const_int 4)))]
6925 )
6926
6927 (define_insn "*arm_cond_branch_reversed"
6928 [(set (pc)
6929 (if_then_else (match_operator 1 "arm_comparison_operator"
6930 [(match_operand 2 "cc_register" "") (const_int 0)])
6931 (pc)
6932 (label_ref (match_operand 0 "" ""))))]
6933 "TARGET_32BIT"
6934 "*
6935 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6936 {
6937 arm_ccfsm_state += 2;
6938 return \"\";
6939 }
6940 return \"b%D1\\t%l0\";
6941 "
6942 [(set_attr "conds" "use")
6943 (set_attr "type" "branch")
6944 (set (attr "length")
6945 (if_then_else
6946 (and (match_test "TARGET_THUMB2")
6947 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
6948 (le (minus (match_dup 0) (pc)) (const_int 256))))
6949 (const_int 2)
6950 (const_int 4)))]
6951 )
6952
6953 \f
6954
6955 ; scc insns
6956
6957 (define_expand "cstore_cc"
6958 [(set (match_operand:SI 0 "s_register_operand")
6959 (match_operator:SI 1 "" [(match_operand 2 "" "")
6960 (match_operand 3 "" "")]))]
6961 "TARGET_32BIT"
6962 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
6963 operands[2], operands[3], NULL_RTX);
6964 operands[3] = const0_rtx;"
6965 )
6966
6967 (define_insn_and_split "*mov_scc"
6968 [(set (match_operand:SI 0 "s_register_operand" "=r")
6969 (match_operator:SI 1 "arm_comparison_operator_mode"
6970 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6971 "TARGET_ARM"
6972 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6973 "TARGET_ARM"
6974 [(set (match_dup 0)
6975 (if_then_else:SI (match_dup 1)
6976 (const_int 1)
6977 (const_int 0)))]
6978 ""
6979 [(set_attr "conds" "use")
6980 (set_attr "length" "8")
6981 (set_attr "type" "multiple")]
6982 )
6983
6984 (define_insn_and_split "*mov_negscc"
6985 [(set (match_operand:SI 0 "s_register_operand" "=r")
6986 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
6987 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6988 "TARGET_ARM"
6989 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6990 "TARGET_ARM"
6991 [(set (match_dup 0)
6992 (if_then_else:SI (match_dup 1)
6993 (match_dup 3)
6994 (const_int 0)))]
6995 {
6996 operands[3] = GEN_INT (~0);
6997 }
6998 [(set_attr "conds" "use")
6999 (set_attr "length" "8")
7000 (set_attr "type" "multiple")]
7001 )
7002
7003 (define_insn_and_split "*mov_notscc"
7004 [(set (match_operand:SI 0 "s_register_operand" "=r")
7005 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7006 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7007 "TARGET_ARM"
7008 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7009 "TARGET_ARM"
7010 [(set (match_dup 0)
7011 (if_then_else:SI (match_dup 1)
7012 (match_dup 3)
7013 (match_dup 4)))]
7014 {
7015 operands[3] = GEN_INT (~1);
7016 operands[4] = GEN_INT (~0);
7017 }
7018 [(set_attr "conds" "use")
7019 (set_attr "length" "8")
7020 (set_attr "type" "multiple")]
7021 )
7022
7023 (define_expand "cstoresi4"
7024 [(set (match_operand:SI 0 "s_register_operand")
7025 (match_operator:SI 1 "expandable_comparison_operator"
7026 [(match_operand:SI 2 "s_register_operand")
7027 (match_operand:SI 3 "reg_or_int_operand")]))]
7028 "TARGET_32BIT || TARGET_THUMB1"
7029 "{
7030 rtx op3, scratch, scratch2;
7031
7032 if (!TARGET_THUMB1)
7033 {
7034 if (!arm_add_operand (operands[3], SImode))
7035 operands[3] = force_reg (SImode, operands[3]);
7036 emit_insn (gen_cstore_cc (operands[0], operands[1],
7037 operands[2], operands[3]));
7038 DONE;
7039 }
7040
7041 if (operands[3] == const0_rtx)
7042 {
7043 switch (GET_CODE (operands[1]))
7044 {
7045 case EQ:
7046 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7047 break;
7048
7049 case NE:
7050 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7051 break;
7052
7053 case LE:
7054 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7055 NULL_RTX, 0, OPTAB_WIDEN);
7056 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7057 NULL_RTX, 0, OPTAB_WIDEN);
7058 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7059 operands[0], 1, OPTAB_WIDEN);
7060 break;
7061
7062 case GE:
7063 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7064 NULL_RTX, 1);
7065 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7066 NULL_RTX, 1, OPTAB_WIDEN);
7067 break;
7068
7069 case GT:
7070 scratch = expand_binop (SImode, ashr_optab, operands[2],
7071 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7072 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7073 NULL_RTX, 0, OPTAB_WIDEN);
7074 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7075 0, OPTAB_WIDEN);
7076 break;
7077
7078 /* LT is handled by generic code. No need for unsigned with 0. */
7079 default:
7080 FAIL;
7081 }
7082 DONE;
7083 }
7084
7085 switch (GET_CODE (operands[1]))
7086 {
7087 case EQ:
7088 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7089 NULL_RTX, 0, OPTAB_WIDEN);
7090 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7091 break;
7092
7093 case NE:
7094 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7095 NULL_RTX, 0, OPTAB_WIDEN);
7096 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7097 break;
7098
7099 case LE:
7100 op3 = force_reg (SImode, operands[3]);
7101
7102 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7103 NULL_RTX, 1, OPTAB_WIDEN);
7104 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7105 NULL_RTX, 0, OPTAB_WIDEN);
7106 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7107 op3, operands[2]));
7108 break;
7109
7110 case GE:
7111 op3 = operands[3];
7112 if (!thumb1_cmp_operand (op3, SImode))
7113 op3 = force_reg (SImode, op3);
7114 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7115 NULL_RTX, 0, OPTAB_WIDEN);
7116 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7117 NULL_RTX, 1, OPTAB_WIDEN);
7118 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7119 operands[2], op3));
7120 break;
7121
7122 case LEU:
7123 op3 = force_reg (SImode, operands[3]);
7124 scratch = force_reg (SImode, const0_rtx);
7125 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7126 op3, operands[2]));
7127 break;
7128
7129 case GEU:
7130 op3 = operands[3];
7131 if (!thumb1_cmp_operand (op3, SImode))
7132 op3 = force_reg (SImode, op3);
7133 scratch = force_reg (SImode, const0_rtx);
7134 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7135 operands[2], op3));
7136 break;
7137
7138 case LTU:
7139 op3 = operands[3];
7140 if (!thumb1_cmp_operand (op3, SImode))
7141 op3 = force_reg (SImode, op3);
7142 scratch = gen_reg_rtx (SImode);
7143 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7144 break;
7145
7146 case GTU:
7147 op3 = force_reg (SImode, operands[3]);
7148 scratch = gen_reg_rtx (SImode);
7149 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7150 break;
7151
7152 /* No good sequences for GT, LT. */
7153 default:
7154 FAIL;
7155 }
7156 DONE;
7157 }")
7158
7159 (define_expand "cstorehf4"
7160 [(set (match_operand:SI 0 "s_register_operand")
7161 (match_operator:SI 1 "expandable_comparison_operator"
7162 [(match_operand:HF 2 "s_register_operand")
7163 (match_operand:HF 3 "vfp_compare_operand")]))]
7164 "TARGET_VFP_FP16INST"
7165 {
7166 if (!arm_validize_comparison (&operands[1],
7167 &operands[2],
7168 &operands[3]))
7169 FAIL;
7170
7171 emit_insn (gen_cstore_cc (operands[0], operands[1],
7172 operands[2], operands[3]));
7173 DONE;
7174 }
7175 )
7176
7177 (define_expand "cstoresf4"
7178 [(set (match_operand:SI 0 "s_register_operand")
7179 (match_operator:SI 1 "expandable_comparison_operator"
7180 [(match_operand:SF 2 "s_register_operand")
7181 (match_operand:SF 3 "vfp_compare_operand")]))]
7182 "TARGET_32BIT && TARGET_HARD_FLOAT"
7183 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7184 operands[2], operands[3])); DONE;"
7185 )
7186
7187 (define_expand "cstoredf4"
7188 [(set (match_operand:SI 0 "s_register_operand")
7189 (match_operator:SI 1 "expandable_comparison_operator"
7190 [(match_operand:DF 2 "s_register_operand")
7191 (match_operand:DF 3 "vfp_compare_operand")]))]
7192 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7193 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7194 operands[2], operands[3])); DONE;"
7195 )
7196
7197 (define_expand "cstoredi4"
7198 [(set (match_operand:SI 0 "s_register_operand")
7199 (match_operator:SI 1 "expandable_comparison_operator"
7200 [(match_operand:DI 2 "s_register_operand")
7201 (match_operand:DI 3 "cmpdi_operand")]))]
7202 "TARGET_32BIT"
7203 "{
7204 if (!arm_validize_comparison (&operands[1],
7205 &operands[2],
7206 &operands[3]))
7207 FAIL;
7208 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7209 operands[3]));
7210 DONE;
7211 }"
7212 )
7213
7214 \f
7215 ;; Conditional move insns
7216
7217 (define_expand "movsicc"
7218 [(set (match_operand:SI 0 "s_register_operand")
7219 (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
7220 (match_operand:SI 2 "arm_not_operand")
7221 (match_operand:SI 3 "arm_not_operand")))]
7222 "TARGET_32BIT"
7223 "
7224 {
7225 enum rtx_code code;
7226 rtx ccreg;
7227
7228 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7229 &XEXP (operands[1], 1)))
7230 FAIL;
7231
7232 code = GET_CODE (operands[1]);
7233 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7234 XEXP (operands[1], 1), NULL_RTX);
7235 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7236 }"
7237 )
7238
7239 (define_expand "movhfcc"
7240 [(set (match_operand:HF 0 "s_register_operand")
7241 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7242 (match_operand:HF 2 "s_register_operand")
7243 (match_operand:HF 3 "s_register_operand")))]
7244 "TARGET_VFP_FP16INST"
7245 "
7246 {
7247 enum rtx_code code = GET_CODE (operands[1]);
7248 rtx ccreg;
7249
7250 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7251 &XEXP (operands[1], 1)))
7252 FAIL;
7253
7254 code = GET_CODE (operands[1]);
7255 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7256 XEXP (operands[1], 1), NULL_RTX);
7257 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7258 }"
7259 )
7260
7261 (define_expand "movsfcc"
7262 [(set (match_operand:SF 0 "s_register_operand")
7263 (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
7264 (match_operand:SF 2 "s_register_operand")
7265 (match_operand:SF 3 "s_register_operand")))]
7266 "TARGET_32BIT && TARGET_HARD_FLOAT"
7267 "
7268 {
7269 enum rtx_code code = GET_CODE (operands[1]);
7270 rtx ccreg;
7271
7272 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7273 &XEXP (operands[1], 1)))
7274 FAIL;
7275
7276 code = GET_CODE (operands[1]);
7277 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7278 XEXP (operands[1], 1), NULL_RTX);
7279 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7280 }"
7281 )
7282
7283 (define_expand "movdfcc"
7284 [(set (match_operand:DF 0 "s_register_operand")
7285 (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
7286 (match_operand:DF 2 "s_register_operand")
7287 (match_operand:DF 3 "s_register_operand")))]
7288 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7289 "
7290 {
7291 enum rtx_code code = GET_CODE (operands[1]);
7292 rtx ccreg;
7293
7294 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7295 &XEXP (operands[1], 1)))
7296 FAIL;
7297 code = GET_CODE (operands[1]);
7298 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7299 XEXP (operands[1], 1), NULL_RTX);
7300 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7301 }"
7302 )
7303
7304 (define_insn "*cmov<mode>"
7305 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7306 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7307 [(match_operand 2 "cc_register" "") (const_int 0)])
7308 (match_operand:SDF 3 "s_register_operand"
7309 "<F_constraint>")
7310 (match_operand:SDF 4 "s_register_operand"
7311 "<F_constraint>")))]
7312 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
7313 "*
7314 {
7315 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7316 switch (code)
7317 {
7318 case ARM_GE:
7319 case ARM_GT:
7320 case ARM_EQ:
7321 case ARM_VS:
7322 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7323 case ARM_LT:
7324 case ARM_LE:
7325 case ARM_NE:
7326 case ARM_VC:
7327 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7328 default:
7329 gcc_unreachable ();
7330 }
7331 return \"\";
7332 }"
7333 [(set_attr "conds" "use")
7334 (set_attr "type" "fcsel")]
7335 )
7336
7337 (define_insn "*cmovhf"
7338 [(set (match_operand:HF 0 "s_register_operand" "=t")
7339 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7340 [(match_operand 2 "cc_register" "") (const_int 0)])
7341 (match_operand:HF 3 "s_register_operand" "t")
7342 (match_operand:HF 4 "s_register_operand" "t")))]
7343 "TARGET_VFP_FP16INST"
7344 "*
7345 {
7346 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7347 switch (code)
7348 {
7349 case ARM_GE:
7350 case ARM_GT:
7351 case ARM_EQ:
7352 case ARM_VS:
7353 return \"vsel%d1.f16\\t%0, %3, %4\";
7354 case ARM_LT:
7355 case ARM_LE:
7356 case ARM_NE:
7357 case ARM_VC:
7358 return \"vsel%D1.f16\\t%0, %4, %3\";
7359 default:
7360 gcc_unreachable ();
7361 }
7362 return \"\";
7363 }"
7364 [(set_attr "conds" "use")
7365 (set_attr "type" "fcsel")]
7366 )
7367
7368 (define_insn_and_split "*movsicc_insn"
7369 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7370 (if_then_else:SI
7371 (match_operator 3 "arm_comparison_operator"
7372 [(match_operand 4 "cc_register" "") (const_int 0)])
7373 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7374 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7375 "TARGET_ARM"
7376 "@
7377 mov%D3\\t%0, %2
7378 mvn%D3\\t%0, #%B2
7379 mov%d3\\t%0, %1
7380 mvn%d3\\t%0, #%B1
7381 #
7382 #
7383 #
7384 #"
7385 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7386 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7387 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7388 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7389 "&& reload_completed"
7390 [(const_int 0)]
7391 {
7392 enum rtx_code rev_code;
7393 machine_mode mode;
7394 rtx rev_cond;
7395
7396 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7397 operands[3],
7398 gen_rtx_SET (operands[0], operands[1])));
7399
7400 rev_code = GET_CODE (operands[3]);
7401 mode = GET_MODE (operands[4]);
7402 if (mode == CCFPmode || mode == CCFPEmode)
7403 rev_code = reverse_condition_maybe_unordered (rev_code);
7404 else
7405 rev_code = reverse_condition (rev_code);
7406
7407 rev_cond = gen_rtx_fmt_ee (rev_code,
7408 VOIDmode,
7409 operands[4],
7410 const0_rtx);
7411 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7412 rev_cond,
7413 gen_rtx_SET (operands[0], operands[2])));
7414 DONE;
7415 }
7416 [(set_attr "length" "4,4,4,4,8,8,8,8")
7417 (set_attr "conds" "use")
7418 (set_attr_alternative "type"
7419 [(if_then_else (match_operand 2 "const_int_operand" "")
7420 (const_string "mov_imm")
7421 (const_string "mov_reg"))
7422 (const_string "mvn_imm")
7423 (if_then_else (match_operand 1 "const_int_operand" "")
7424 (const_string "mov_imm")
7425 (const_string "mov_reg"))
7426 (const_string "mvn_imm")
7427 (const_string "multiple")
7428 (const_string "multiple")
7429 (const_string "multiple")
7430 (const_string "multiple")])]
7431 )
7432
7433 (define_insn "*movsfcc_soft_insn"
7434 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7435 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7436 [(match_operand 4 "cc_register" "") (const_int 0)])
7437 (match_operand:SF 1 "s_register_operand" "0,r")
7438 (match_operand:SF 2 "s_register_operand" "r,0")))]
7439 "TARGET_ARM && TARGET_SOFT_FLOAT"
7440 "@
7441 mov%D3\\t%0, %2
7442 mov%d3\\t%0, %1"
7443 [(set_attr "conds" "use")
7444 (set_attr "type" "mov_reg")]
7445 )
7446
7447 \f
7448 ;; Jump and linkage insns
7449
7450 (define_expand "jump"
7451 [(set (pc)
7452 (label_ref (match_operand 0 "" "")))]
7453 "TARGET_EITHER"
7454 ""
7455 )
7456
7457 (define_insn "*arm_jump"
7458 [(set (pc)
7459 (label_ref (match_operand 0 "" "")))]
7460 "TARGET_32BIT"
7461 "*
7462 {
7463 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7464 {
7465 arm_ccfsm_state += 2;
7466 return \"\";
7467 }
7468 return \"b%?\\t%l0\";
7469 }
7470 "
7471 [(set_attr "predicable" "yes")
7472 (set (attr "length")
7473 (if_then_else
7474 (and (match_test "TARGET_THUMB2")
7475 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7476 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7477 (const_int 2)
7478 (const_int 4)))
7479 (set_attr "type" "branch")]
7480 )
7481
7482 (define_expand "call"
7483 [(parallel [(call (match_operand 0 "memory_operand")
7484 (match_operand 1 "general_operand"))
7485 (use (match_operand 2 "" ""))
7486 (clobber (reg:SI LR_REGNUM))])]
7487 "TARGET_EITHER"
7488 "
7489 {
7490 rtx callee, pat;
7491 tree addr = MEM_EXPR (operands[0]);
7492
7493 /* In an untyped call, we can get NULL for operand 2. */
7494 if (operands[2] == NULL_RTX)
7495 operands[2] = const0_rtx;
7496
7497 /* Decide if we should generate indirect calls by loading the
7498 32-bit address of the callee into a register before performing the
7499 branch and link. */
7500 callee = XEXP (operands[0], 0);
7501 if (GET_CODE (callee) == SYMBOL_REF
7502 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7503 : !REG_P (callee))
7504 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7505
7506 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[0], 0)))
7507 /* Indirect call: set r9 with FDPIC value of callee. */
7508 XEXP (operands[0], 0)
7509 = arm_load_function_descriptor (XEXP (operands[0], 0));
7510
7511 if (detect_cmse_nonsecure_call (addr))
7512 {
7513 pat = gen_nonsecure_call_internal (operands[0], operands[1],
7514 operands[2]);
7515 emit_call_insn (pat);
7516 }
7517 else
7518 {
7519 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7520 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
7521 }
7522
7523 /* Restore FDPIC register (r9) after call. */
7524 if (TARGET_FDPIC)
7525 {
7526 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7527 rtx initial_fdpic_reg
7528 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7529
7530 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7531 initial_fdpic_reg));
7532 }
7533
7534 DONE;
7535 }"
7536 )
7537
7538 (define_insn "restore_pic_register_after_call"
7539 [(set (match_operand:SI 0 "s_register_operand" "+r,r")
7540 (unspec:SI [(match_dup 0)
7541 (match_operand:SI 1 "nonimmediate_operand" "r,m")]
7542 UNSPEC_PIC_RESTORE))]
7543 ""
7544 "@
7545 mov\t%0, %1
7546 ldr\t%0, %1"
7547 )
7548
7549 (define_expand "call_internal"
7550 [(parallel [(call (match_operand 0 "memory_operand")
7551 (match_operand 1 "general_operand"))
7552 (use (match_operand 2 "" ""))
7553 (clobber (reg:SI LR_REGNUM))])])
7554
7555 (define_expand "nonsecure_call_internal"
7556 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
7557 UNSPEC_NONSECURE_MEM)
7558 (match_operand 1 "general_operand"))
7559 (use (match_operand 2 "" ""))
7560 (clobber (reg:SI LR_REGNUM))])]
7561 "use_cmse"
7562 "
7563 {
7564 rtx tmp;
7565 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
7566 gen_rtx_REG (SImode, R4_REGNUM),
7567 SImode);
7568
7569 operands[0] = replace_equiv_address (operands[0], tmp);
7570 }")
7571
7572 (define_insn "*call_reg_armv5"
7573 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7574 (match_operand 1 "" ""))
7575 (use (match_operand 2 "" ""))
7576 (clobber (reg:SI LR_REGNUM))]
7577 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
7578 "blx%?\\t%0"
7579 [(set_attr "type" "call")]
7580 )
7581
7582 (define_insn "*call_reg_arm"
7583 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7584 (match_operand 1 "" ""))
7585 (use (match_operand 2 "" ""))
7586 (clobber (reg:SI LR_REGNUM))]
7587 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
7588 "*
7589 return output_call (operands);
7590 "
7591 ;; length is worst case, normally it is only two
7592 [(set_attr "length" "12")
7593 (set_attr "type" "call")]
7594 )
7595
7596
7597 (define_expand "call_value"
7598 [(parallel [(set (match_operand 0 "" "")
7599 (call (match_operand 1 "memory_operand")
7600 (match_operand 2 "general_operand")))
7601 (use (match_operand 3 "" ""))
7602 (clobber (reg:SI LR_REGNUM))])]
7603 "TARGET_EITHER"
7604 "
7605 {
7606 rtx pat, callee;
7607 tree addr = MEM_EXPR (operands[1]);
7608
7609 /* In an untyped call, we can get NULL for operand 2. */
7610 if (operands[3] == 0)
7611 operands[3] = const0_rtx;
7612
7613 /* Decide if we should generate indirect calls by loading the
7614 32-bit address of the callee into a register before performing the
7615 branch and link. */
7616 callee = XEXP (operands[1], 0);
7617 if (GET_CODE (callee) == SYMBOL_REF
7618 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7619 : !REG_P (callee))
7620 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7621
7622 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[1], 0)))
7623 /* Indirect call: set r9 with FDPIC value of callee. */
7624 XEXP (operands[1], 0)
7625 = arm_load_function_descriptor (XEXP (operands[1], 0));
7626
7627 if (detect_cmse_nonsecure_call (addr))
7628 {
7629 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
7630 operands[2], operands[3]);
7631 emit_call_insn (pat);
7632 }
7633 else
7634 {
7635 pat = gen_call_value_internal (operands[0], operands[1],
7636 operands[2], operands[3]);
7637 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
7638 }
7639
7640 /* Restore FDPIC register (r9) after call. */
7641 if (TARGET_FDPIC)
7642 {
7643 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7644 rtx initial_fdpic_reg
7645 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7646
7647 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7648 initial_fdpic_reg));
7649 }
7650
7651 DONE;
7652 }"
7653 )
7654
7655 (define_expand "call_value_internal"
7656 [(parallel [(set (match_operand 0 "" "")
7657 (call (match_operand 1 "memory_operand")
7658 (match_operand 2 "general_operand")))
7659 (use (match_operand 3 "" ""))
7660 (clobber (reg:SI LR_REGNUM))])])
7661
7662 (define_expand "nonsecure_call_value_internal"
7663 [(parallel [(set (match_operand 0 "" "")
7664 (call (unspec:SI [(match_operand 1 "memory_operand")]
7665 UNSPEC_NONSECURE_MEM)
7666 (match_operand 2 "general_operand")))
7667 (use (match_operand 3 "" ""))
7668 (clobber (reg:SI LR_REGNUM))])]
7669 "use_cmse"
7670 "
7671 {
7672 rtx tmp;
7673 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
7674 gen_rtx_REG (SImode, R4_REGNUM),
7675 SImode);
7676
7677 operands[1] = replace_equiv_address (operands[1], tmp);
7678 }")
7679
7680 (define_insn "*call_value_reg_armv5"
7681 [(set (match_operand 0 "" "")
7682 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7683 (match_operand 2 "" "")))
7684 (use (match_operand 3 "" ""))
7685 (clobber (reg:SI LR_REGNUM))]
7686 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
7687 "blx%?\\t%1"
7688 [(set_attr "type" "call")]
7689 )
7690
7691 (define_insn "*call_value_reg_arm"
7692 [(set (match_operand 0 "" "")
7693 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7694 (match_operand 2 "" "")))
7695 (use (match_operand 3 "" ""))
7696 (clobber (reg:SI LR_REGNUM))]
7697 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
7698 "*
7699 return output_call (&operands[1]);
7700 "
7701 [(set_attr "length" "12")
7702 (set_attr "type" "call")]
7703 )
7704
7705 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7706 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7707
7708 (define_insn "*call_symbol"
7709 [(call (mem:SI (match_operand:SI 0 "" ""))
7710 (match_operand 1 "" ""))
7711 (use (match_operand 2 "" ""))
7712 (clobber (reg:SI LR_REGNUM))]
7713 "TARGET_32BIT
7714 && !SIBLING_CALL_P (insn)
7715 && (GET_CODE (operands[0]) == SYMBOL_REF)
7716 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
7717 "*
7718 {
7719 rtx op = operands[0];
7720
7721 /* Switch mode now when possible. */
7722 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7723 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7724 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7725
7726 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7727 }"
7728 [(set_attr "type" "call")]
7729 )
7730
7731 (define_insn "*call_value_symbol"
7732 [(set (match_operand 0 "" "")
7733 (call (mem:SI (match_operand:SI 1 "" ""))
7734 (match_operand:SI 2 "" "")))
7735 (use (match_operand 3 "" ""))
7736 (clobber (reg:SI LR_REGNUM))]
7737 "TARGET_32BIT
7738 && !SIBLING_CALL_P (insn)
7739 && (GET_CODE (operands[1]) == SYMBOL_REF)
7740 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
7741 "*
7742 {
7743 rtx op = operands[1];
7744
7745 /* Switch mode now when possible. */
7746 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7747 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7748 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
7749
7750 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7751 }"
7752 [(set_attr "type" "call")]
7753 )
7754
7755 (define_expand "sibcall_internal"
7756 [(parallel [(call (match_operand 0 "memory_operand")
7757 (match_operand 1 "general_operand"))
7758 (return)
7759 (use (match_operand 2 "" ""))])])
7760
7761 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7762 (define_expand "sibcall"
7763 [(parallel [(call (match_operand 0 "memory_operand")
7764 (match_operand 1 "general_operand"))
7765 (return)
7766 (use (match_operand 2 "" ""))])]
7767 "TARGET_32BIT"
7768 "
7769 {
7770 rtx pat;
7771
7772 if ((!REG_P (XEXP (operands[0], 0))
7773 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7774 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7775 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
7776 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7777
7778 if (operands[2] == NULL_RTX)
7779 operands[2] = const0_rtx;
7780
7781 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7782 arm_emit_call_insn (pat, operands[0], true);
7783 DONE;
7784 }"
7785 )
7786
7787 (define_expand "sibcall_value_internal"
7788 [(parallel [(set (match_operand 0 "" "")
7789 (call (match_operand 1 "memory_operand")
7790 (match_operand 2 "general_operand")))
7791 (return)
7792 (use (match_operand 3 "" ""))])])
7793
7794 (define_expand "sibcall_value"
7795 [(parallel [(set (match_operand 0 "" "")
7796 (call (match_operand 1 "memory_operand")
7797 (match_operand 2 "general_operand")))
7798 (return)
7799 (use (match_operand 3 "" ""))])]
7800 "TARGET_32BIT"
7801 "
7802 {
7803 rtx pat;
7804
7805 if ((!REG_P (XEXP (operands[1], 0))
7806 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7807 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7808 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
7809 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7810
7811 if (operands[3] == NULL_RTX)
7812 operands[3] = const0_rtx;
7813
7814 pat = gen_sibcall_value_internal (operands[0], operands[1],
7815 operands[2], operands[3]);
7816 arm_emit_call_insn (pat, operands[1], true);
7817 DONE;
7818 }"
7819 )
7820
7821 (define_insn "*sibcall_insn"
7822 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
7823 (match_operand 1 "" ""))
7824 (return)
7825 (use (match_operand 2 "" ""))]
7826 "TARGET_32BIT && SIBLING_CALL_P (insn)"
7827 "*
7828 if (which_alternative == 1)
7829 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7830 else
7831 {
7832 if (arm_arch5t || arm_arch4t)
7833 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
7834 else
7835 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7836 }
7837 "
7838 [(set_attr "type" "call")]
7839 )
7840
7841 (define_insn "*sibcall_value_insn"
7842 [(set (match_operand 0 "" "")
7843 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
7844 (match_operand 2 "" "")))
7845 (return)
7846 (use (match_operand 3 "" ""))]
7847 "TARGET_32BIT && SIBLING_CALL_P (insn)"
7848 "*
7849 if (which_alternative == 1)
7850 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7851 else
7852 {
7853 if (arm_arch5t || arm_arch4t)
7854 return \"bx%?\\t%1\";
7855 else
7856 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7857 }
7858 "
7859 [(set_attr "type" "call")]
7860 )
7861
7862 (define_expand "<return_str>return"
7863 [(RETURNS)]
7864 "(TARGET_ARM || (TARGET_THUMB2
7865 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7866 && !IS_STACKALIGN (arm_current_func_type ())))
7867 <return_cond_false>"
7868 "
7869 {
7870 if (TARGET_THUMB2)
7871 {
7872 thumb2_expand_return (<return_simple_p>);
7873 DONE;
7874 }
7875 }
7876 "
7877 )
7878
7879 ;; Often the return insn will be the same as loading from memory, so set attr
7880 (define_insn "*arm_return"
7881 [(return)]
7882 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7883 "*
7884 {
7885 if (arm_ccfsm_state == 2)
7886 {
7887 arm_ccfsm_state += 2;
7888 return \"\";
7889 }
7890 return output_return_instruction (const_true_rtx, true, false, false);
7891 }"
7892 [(set_attr "type" "load_4")
7893 (set_attr "length" "12")
7894 (set_attr "predicable" "yes")]
7895 )
7896
7897 (define_insn "*cond_<return_str>return"
7898 [(set (pc)
7899 (if_then_else (match_operator 0 "arm_comparison_operator"
7900 [(match_operand 1 "cc_register" "") (const_int 0)])
7901 (RETURNS)
7902 (pc)))]
7903 "TARGET_ARM <return_cond_true>"
7904 "*
7905 {
7906 if (arm_ccfsm_state == 2)
7907 {
7908 arm_ccfsm_state += 2;
7909 return \"\";
7910 }
7911 return output_return_instruction (operands[0], true, false,
7912 <return_simple_p>);
7913 }"
7914 [(set_attr "conds" "use")
7915 (set_attr "length" "12")
7916 (set_attr "type" "load_4")]
7917 )
7918
7919 (define_insn "*cond_<return_str>return_inverted"
7920 [(set (pc)
7921 (if_then_else (match_operator 0 "arm_comparison_operator"
7922 [(match_operand 1 "cc_register" "") (const_int 0)])
7923 (pc)
7924 (RETURNS)))]
7925 "TARGET_ARM <return_cond_true>"
7926 "*
7927 {
7928 if (arm_ccfsm_state == 2)
7929 {
7930 arm_ccfsm_state += 2;
7931 return \"\";
7932 }
7933 return output_return_instruction (operands[0], true, true,
7934 <return_simple_p>);
7935 }"
7936 [(set_attr "conds" "use")
7937 (set_attr "length" "12")
7938 (set_attr "type" "load_4")]
7939 )
7940
7941 (define_insn "*arm_simple_return"
7942 [(simple_return)]
7943 "TARGET_ARM"
7944 "*
7945 {
7946 if (arm_ccfsm_state == 2)
7947 {
7948 arm_ccfsm_state += 2;
7949 return \"\";
7950 }
7951 return output_return_instruction (const_true_rtx, true, false, true);
7952 }"
7953 [(set_attr "type" "branch")
7954 (set_attr "length" "4")
7955 (set_attr "predicable" "yes")]
7956 )
7957
7958 ;; Generate a sequence of instructions to determine if the processor is
7959 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7960 ;; mask.
7961
7962 (define_expand "return_addr_mask"
7963 [(set (match_dup 1)
7964 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7965 (const_int 0)))
7966 (set (match_operand:SI 0 "s_register_operand")
7967 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7968 (const_int -1)
7969 (const_int 67108860)))] ; 0x03fffffc
7970 "TARGET_ARM"
7971 "
7972 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7973 ")
7974
7975 (define_insn "*check_arch2"
7976 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7977 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7978 (const_int 0)))]
7979 "TARGET_ARM"
7980 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7981 [(set_attr "length" "8")
7982 (set_attr "conds" "set")
7983 (set_attr "type" "multiple")]
7984 )
7985
7986 ;; Call subroutine returning any type.
7987
7988 (define_expand "untyped_call"
7989 [(parallel [(call (match_operand 0 "" "")
7990 (const_int 0))
7991 (match_operand 1 "" "")
7992 (match_operand 2 "" "")])]
7993 "TARGET_EITHER && !TARGET_FDPIC"
7994 "
7995 {
7996 int i;
7997 rtx par = gen_rtx_PARALLEL (VOIDmode,
7998 rtvec_alloc (XVECLEN (operands[2], 0)));
7999 rtx addr = gen_reg_rtx (Pmode);
8000 rtx mem;
8001 int size = 0;
8002
8003 emit_move_insn (addr, XEXP (operands[1], 0));
8004 mem = change_address (operands[1], BLKmode, addr);
8005
8006 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8007 {
8008 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8009
8010 /* Default code only uses r0 as a return value, but we could
8011 be using anything up to 4 registers. */
8012 if (REGNO (src) == R0_REGNUM)
8013 src = gen_rtx_REG (TImode, R0_REGNUM);
8014
8015 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8016 GEN_INT (size));
8017 size += GET_MODE_SIZE (GET_MODE (src));
8018 }
8019
8020 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
8021
8022 size = 0;
8023
8024 for (i = 0; i < XVECLEN (par, 0); i++)
8025 {
8026 HOST_WIDE_INT offset = 0;
8027 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8028
8029 if (size != 0)
8030 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8031
8032 mem = change_address (mem, GET_MODE (reg), NULL);
8033 if (REGNO (reg) == R0_REGNUM)
8034 {
8035 /* On thumb we have to use a write-back instruction. */
8036 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8037 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8038 size = TARGET_ARM ? 16 : 0;
8039 }
8040 else
8041 {
8042 emit_move_insn (mem, reg);
8043 size = GET_MODE_SIZE (GET_MODE (reg));
8044 }
8045 }
8046
8047 /* The optimizer does not know that the call sets the function value
8048 registers we stored in the result block. We avoid problems by
8049 claiming that all hard registers are used and clobbered at this
8050 point. */
8051 emit_insn (gen_blockage ());
8052
8053 DONE;
8054 }"
8055 )
8056
8057 (define_expand "untyped_return"
8058 [(match_operand:BLK 0 "memory_operand")
8059 (match_operand 1 "" "")]
8060 "TARGET_EITHER && !TARGET_FDPIC"
8061 "
8062 {
8063 int i;
8064 rtx addr = gen_reg_rtx (Pmode);
8065 rtx mem;
8066 int size = 0;
8067
8068 emit_move_insn (addr, XEXP (operands[0], 0));
8069 mem = change_address (operands[0], BLKmode, addr);
8070
8071 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8072 {
8073 HOST_WIDE_INT offset = 0;
8074 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8075
8076 if (size != 0)
8077 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8078
8079 mem = change_address (mem, GET_MODE (reg), NULL);
8080 if (REGNO (reg) == R0_REGNUM)
8081 {
8082 /* On thumb we have to use a write-back instruction. */
8083 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8084 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8085 size = TARGET_ARM ? 16 : 0;
8086 }
8087 else
8088 {
8089 emit_move_insn (reg, mem);
8090 size = GET_MODE_SIZE (GET_MODE (reg));
8091 }
8092 }
8093
8094 /* Emit USE insns before the return. */
8095 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8096 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8097
8098 /* Construct the return. */
8099 expand_naked_return ();
8100
8101 DONE;
8102 }"
8103 )
8104
8105 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8106 ;; all of memory. This blocks insns from being moved across this point.
8107
8108 (define_insn "blockage"
8109 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8110 "TARGET_EITHER"
8111 ""
8112 [(set_attr "length" "0")
8113 (set_attr "type" "block")]
8114 )
8115
8116 ;; Since we hard code r0 here use the 'o' constraint to prevent
8117 ;; provoking undefined behaviour in the hardware with putting out
8118 ;; auto-increment operations with potentially r0 as the base register.
8119 (define_insn "probe_stack"
8120 [(set (match_operand:SI 0 "memory_operand" "=o")
8121 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
8122 "TARGET_32BIT"
8123 "str%?\\tr0, %0"
8124 [(set_attr "type" "store_4")
8125 (set_attr "predicable" "yes")]
8126 )
8127
8128 (define_insn "probe_stack_range"
8129 [(set (match_operand:SI 0 "register_operand" "=r")
8130 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8131 (match_operand:SI 2 "register_operand" "r")]
8132 VUNSPEC_PROBE_STACK_RANGE))]
8133 "TARGET_32BIT"
8134 {
8135 return output_probe_stack_range (operands[0], operands[2]);
8136 }
8137 [(set_attr "type" "multiple")
8138 (set_attr "conds" "clob")]
8139 )
8140
8141 ;; Named patterns for stack smashing protection.
8142 (define_expand "stack_protect_combined_set"
8143 [(parallel
8144 [(set (match_operand:SI 0 "memory_operand")
8145 (unspec:SI [(match_operand:SI 1 "guard_operand")]
8146 UNSPEC_SP_SET))
8147 (clobber (match_scratch:SI 2 ""))
8148 (clobber (match_scratch:SI 3 ""))])]
8149 ""
8150 ""
8151 )
8152
8153 ;; Use a separate insn from the above expand to be able to have the mem outside
8154 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8155 ;; try to reload the guard since we need to control how PIC access is done in
8156 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8157 ;; legitimize_pic_address ()).
8158 (define_insn_and_split "*stack_protect_combined_set_insn"
8159 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8160 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8161 UNSPEC_SP_SET))
8162 (clobber (match_scratch:SI 2 "=&l,&r"))
8163 (clobber (match_scratch:SI 3 "=&l,&r"))]
8164 ""
8165 "#"
8166 "reload_completed"
8167 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8168 UNSPEC_SP_SET))
8169 (clobber (match_dup 2))])]
8170 "
8171 {
8172 if (flag_pic)
8173 {
8174 rtx pic_reg;
8175
8176 if (TARGET_FDPIC)
8177 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8178 else
8179 pic_reg = operands[3];
8180
8181 /* Forces recomputing of GOT base now. */
8182 legitimize_pic_address (operands[1], SImode, operands[2], pic_reg,
8183 true /*compute_now*/);
8184 }
8185 else
8186 {
8187 if (address_operand (operands[1], SImode))
8188 operands[2] = operands[1];
8189 else
8190 {
8191 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8192 emit_move_insn (operands[2], mem);
8193 }
8194 }
8195 }"
8196 [(set_attr "arch" "t1,32")]
8197 )
8198
8199 ;; DO NOT SPLIT THIS INSN. It's important for security reasons that the
8200 ;; canary value does not live beyond the life of this sequence.
8201 (define_insn "*stack_protect_set_insn"
8202 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8203 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8204 UNSPEC_SP_SET))
8205 (clobber (match_dup 1))]
8206 ""
8207 "@
8208 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1, #0
8209 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1, #0"
8210 [(set_attr "length" "8,12")
8211 (set_attr "conds" "clob,nocond")
8212 (set_attr "type" "multiple")
8213 (set_attr "arch" "t1,32")]
8214 )
8215
8216 (define_expand "stack_protect_combined_test"
8217 [(parallel
8218 [(set (pc)
8219 (if_then_else
8220 (eq (match_operand:SI 0 "memory_operand")
8221 (unspec:SI [(match_operand:SI 1 "guard_operand")]
8222 UNSPEC_SP_TEST))
8223 (label_ref (match_operand 2))
8224 (pc)))
8225 (clobber (match_scratch:SI 3 ""))
8226 (clobber (match_scratch:SI 4 ""))
8227 (clobber (reg:CC CC_REGNUM))])]
8228 ""
8229 ""
8230 )
8231
8232 ;; Use a separate insn from the above expand to be able to have the mem outside
8233 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8234 ;; try to reload the guard since we need to control how PIC access is done in
8235 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8236 ;; legitimize_pic_address ()).
8237 (define_insn_and_split "*stack_protect_combined_test_insn"
8238 [(set (pc)
8239 (if_then_else
8240 (eq (match_operand:SI 0 "memory_operand" "m,m")
8241 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8242 UNSPEC_SP_TEST))
8243 (label_ref (match_operand 2))
8244 (pc)))
8245 (clobber (match_scratch:SI 3 "=&l,&r"))
8246 (clobber (match_scratch:SI 4 "=&l,&r"))
8247 (clobber (reg:CC CC_REGNUM))]
8248 ""
8249 "#"
8250 "reload_completed"
8251 [(const_int 0)]
8252 {
8253 rtx eq;
8254
8255 if (flag_pic)
8256 {
8257 rtx pic_reg;
8258
8259 if (TARGET_FDPIC)
8260 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8261 else
8262 pic_reg = operands[4];
8263
8264 /* Forces recomputing of GOT base now. */
8265 legitimize_pic_address (operands[1], SImode, operands[3], pic_reg,
8266 true /*compute_now*/);
8267 }
8268 else
8269 {
8270 if (address_operand (operands[1], SImode))
8271 operands[3] = operands[1];
8272 else
8273 {
8274 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8275 emit_move_insn (operands[3], mem);
8276 }
8277 }
8278 if (TARGET_32BIT)
8279 {
8280 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8281 operands[3]));
8282 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8283 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8284 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8285 }
8286 else
8287 {
8288 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8289 operands[3]));
8290 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8291 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8292 operands[2]));
8293 }
8294 DONE;
8295 }
8296 [(set_attr "arch" "t1,32")]
8297 )
8298
8299 (define_insn "arm_stack_protect_test_insn"
8300 [(set (reg:CC_Z CC_REGNUM)
8301 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8302 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8303 UNSPEC_SP_TEST)
8304 (const_int 0)))
8305 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8306 (clobber (match_dup 2))]
8307 "TARGET_32BIT"
8308 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8309 [(set_attr "length" "8,12")
8310 (set_attr "conds" "set")
8311 (set_attr "type" "multiple")
8312 (set_attr "arch" "t,32")]
8313 )
8314
8315 (define_expand "casesi"
8316 [(match_operand:SI 0 "s_register_operand") ; index to jump on
8317 (match_operand:SI 1 "const_int_operand") ; lower bound
8318 (match_operand:SI 2 "const_int_operand") ; total range
8319 (match_operand:SI 3 "" "") ; table label
8320 (match_operand:SI 4 "" "")] ; Out of range label
8321 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
8322 "
8323 {
8324 enum insn_code code;
8325 if (operands[1] != const0_rtx)
8326 {
8327 rtx reg = gen_reg_rtx (SImode);
8328
8329 emit_insn (gen_addsi3 (reg, operands[0],
8330 gen_int_mode (-INTVAL (operands[1]),
8331 SImode)));
8332 operands[0] = reg;
8333 }
8334
8335 if (TARGET_ARM)
8336 code = CODE_FOR_arm_casesi_internal;
8337 else if (TARGET_THUMB1)
8338 code = CODE_FOR_thumb1_casesi_internal_pic;
8339 else if (flag_pic)
8340 code = CODE_FOR_thumb2_casesi_internal_pic;
8341 else
8342 code = CODE_FOR_thumb2_casesi_internal;
8343
8344 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8345 operands[2] = force_reg (SImode, operands[2]);
8346
8347 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8348 operands[3], operands[4]));
8349 DONE;
8350 }"
8351 )
8352
8353 ;; The USE in this pattern is needed to tell flow analysis that this is
8354 ;; a CASESI insn. It has no other purpose.
8355 (define_expand "arm_casesi_internal"
8356 [(parallel [(set (pc)
8357 (if_then_else
8358 (leu (match_operand:SI 0 "s_register_operand")
8359 (match_operand:SI 1 "arm_rhs_operand"))
8360 (match_dup 4)
8361 (label_ref:SI (match_operand 3 ""))))
8362 (clobber (reg:CC CC_REGNUM))
8363 (use (label_ref:SI (match_operand 2 "")))])]
8364 "TARGET_ARM"
8365 {
8366 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8367 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8368 gen_rtx_LABEL_REF (SImode, operands[2]));
8369 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8370 MEM_READONLY_P (operands[4]) = 1;
8371 MEM_NOTRAP_P (operands[4]) = 1;
8372 })
8373
8374 (define_insn "*arm_casesi_internal"
8375 [(parallel [(set (pc)
8376 (if_then_else
8377 (leu (match_operand:SI 0 "s_register_operand" "r")
8378 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8379 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8380 (label_ref:SI (match_operand 2 "" ""))))
8381 (label_ref:SI (match_operand 3 "" ""))))
8382 (clobber (reg:CC CC_REGNUM))
8383 (use (label_ref:SI (match_dup 2)))])]
8384 "TARGET_ARM"
8385 "*
8386 if (flag_pic)
8387 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8388 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8389 "
8390 [(set_attr "conds" "clob")
8391 (set_attr "length" "12")
8392 (set_attr "type" "multiple")]
8393 )
8394
8395 (define_expand "indirect_jump"
8396 [(set (pc)
8397 (match_operand:SI 0 "s_register_operand"))]
8398 "TARGET_EITHER"
8399 "
8400 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8401 address and use bx. */
8402 if (TARGET_THUMB2)
8403 {
8404 rtx tmp;
8405 tmp = gen_reg_rtx (SImode);
8406 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8407 operands[0] = tmp;
8408 }
8409 "
8410 )
8411
8412 ;; NB Never uses BX.
8413 (define_insn "*arm_indirect_jump"
8414 [(set (pc)
8415 (match_operand:SI 0 "s_register_operand" "r"))]
8416 "TARGET_ARM"
8417 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8418 [(set_attr "predicable" "yes")
8419 (set_attr "type" "branch")]
8420 )
8421
8422 (define_insn "*load_indirect_jump"
8423 [(set (pc)
8424 (match_operand:SI 0 "memory_operand" "m"))]
8425 "TARGET_ARM"
8426 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8427 [(set_attr "type" "load_4")
8428 (set_attr "pool_range" "4096")
8429 (set_attr "neg_pool_range" "4084")
8430 (set_attr "predicable" "yes")]
8431 )
8432
8433 \f
8434 ;; Misc insns
8435
8436 (define_insn "nop"
8437 [(const_int 0)]
8438 "TARGET_EITHER"
8439 "nop"
8440 [(set (attr "length")
8441 (if_then_else (eq_attr "is_thumb" "yes")
8442 (const_int 2)
8443 (const_int 4)))
8444 (set_attr "type" "mov_reg")]
8445 )
8446
8447 (define_insn "trap"
8448 [(trap_if (const_int 1) (const_int 0))]
8449 ""
8450 "*
8451 if (TARGET_ARM)
8452 return \".inst\\t0xe7f000f0\";
8453 else
8454 return \".inst\\t0xdeff\";
8455 "
8456 [(set (attr "length")
8457 (if_then_else (eq_attr "is_thumb" "yes")
8458 (const_int 2)
8459 (const_int 4)))
8460 (set_attr "type" "trap")
8461 (set_attr "conds" "unconditional")]
8462 )
8463
8464 \f
8465 ;; Patterns to allow combination of arithmetic, cond code and shifts
8466
8467 (define_insn "*<arith_shift_insn>_multsi"
8468 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8469 (SHIFTABLE_OPS:SI
8470 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8471 (match_operand:SI 3 "power_of_two_operand" ""))
8472 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
8473 "TARGET_32BIT"
8474 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8475 [(set_attr "predicable" "yes")
8476 (set_attr "shift" "2")
8477 (set_attr "arch" "a,t2")
8478 (set_attr "type" "alu_shift_imm")])
8479
8480 (define_insn "*<arith_shift_insn>_shiftsi"
8481 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8482 (SHIFTABLE_OPS:SI
8483 (match_operator:SI 2 "shift_nomul_operator"
8484 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8485 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8486 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
8487 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
8488 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
8489 [(set_attr "predicable" "yes")
8490 (set_attr "shift" "3")
8491 (set_attr "arch" "a,t2,a")
8492 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
8493
8494 (define_split
8495 [(set (match_operand:SI 0 "s_register_operand" "")
8496 (match_operator:SI 1 "shiftable_operator"
8497 [(match_operator:SI 2 "shiftable_operator"
8498 [(match_operator:SI 3 "shift_operator"
8499 [(match_operand:SI 4 "s_register_operand" "")
8500 (match_operand:SI 5 "reg_or_int_operand" "")])
8501 (match_operand:SI 6 "s_register_operand" "")])
8502 (match_operand:SI 7 "arm_rhs_operand" "")]))
8503 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8504 "TARGET_32BIT"
8505 [(set (match_dup 8)
8506 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8507 (match_dup 6)]))
8508 (set (match_dup 0)
8509 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8510 "")
8511
8512 (define_insn "*arith_shiftsi_compare0"
8513 [(set (reg:CC_NOOV CC_REGNUM)
8514 (compare:CC_NOOV
8515 (match_operator:SI 1 "shiftable_operator"
8516 [(match_operator:SI 3 "shift_operator"
8517 [(match_operand:SI 4 "s_register_operand" "r,r")
8518 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8519 (match_operand:SI 2 "s_register_operand" "r,r")])
8520 (const_int 0)))
8521 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8522 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8523 (match_dup 2)]))]
8524 "TARGET_32BIT"
8525 "%i1s%?\\t%0, %2, %4%S3"
8526 [(set_attr "conds" "set")
8527 (set_attr "shift" "4")
8528 (set_attr "arch" "32,a")
8529 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8530
8531 (define_insn "*arith_shiftsi_compare0_scratch"
8532 [(set (reg:CC_NOOV CC_REGNUM)
8533 (compare:CC_NOOV
8534 (match_operator:SI 1 "shiftable_operator"
8535 [(match_operator:SI 3 "shift_operator"
8536 [(match_operand:SI 4 "s_register_operand" "r,r")
8537 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8538 (match_operand:SI 2 "s_register_operand" "r,r")])
8539 (const_int 0)))
8540 (clobber (match_scratch:SI 0 "=r,r"))]
8541 "TARGET_32BIT"
8542 "%i1s%?\\t%0, %2, %4%S3"
8543 [(set_attr "conds" "set")
8544 (set_attr "shift" "4")
8545 (set_attr "arch" "32,a")
8546 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8547
8548 (define_insn "*sub_shiftsi"
8549 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8550 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8551 (match_operator:SI 2 "shift_operator"
8552 [(match_operand:SI 3 "s_register_operand" "r,r")
8553 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8554 "TARGET_32BIT"
8555 "sub%?\\t%0, %1, %3%S2"
8556 [(set_attr "predicable" "yes")
8557 (set_attr "predicable_short_it" "no")
8558 (set_attr "shift" "3")
8559 (set_attr "arch" "32,a")
8560 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8561
8562 (define_insn "*sub_shiftsi_compare0"
8563 [(set (reg:CC_NOOV CC_REGNUM)
8564 (compare:CC_NOOV
8565 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8566 (match_operator:SI 2 "shift_operator"
8567 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8568 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8569 (const_int 0)))
8570 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8571 (minus:SI (match_dup 1)
8572 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8573 "TARGET_32BIT"
8574 "subs%?\\t%0, %1, %3%S2"
8575 [(set_attr "conds" "set")
8576 (set_attr "shift" "3")
8577 (set_attr "arch" "32,a,a")
8578 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8579
8580 (define_insn "*sub_shiftsi_compare0_scratch"
8581 [(set (reg:CC_NOOV CC_REGNUM)
8582 (compare:CC_NOOV
8583 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8584 (match_operator:SI 2 "shift_operator"
8585 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8586 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8587 (const_int 0)))
8588 (clobber (match_scratch:SI 0 "=r,r,r"))]
8589 "TARGET_32BIT"
8590 "subs%?\\t%0, %1, %3%S2"
8591 [(set_attr "conds" "set")
8592 (set_attr "shift" "3")
8593 (set_attr "arch" "32,a,a")
8594 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8595 \f
8596
8597 (define_insn_and_split "*and_scc"
8598 [(set (match_operand:SI 0 "s_register_operand" "=r")
8599 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8600 [(match_operand 2 "cc_register" "") (const_int 0)])
8601 (match_operand:SI 3 "s_register_operand" "r")))]
8602 "TARGET_ARM"
8603 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8604 "&& reload_completed"
8605 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8606 (cond_exec (match_dup 4) (set (match_dup 0)
8607 (and:SI (match_dup 3) (const_int 1))))]
8608 {
8609 machine_mode mode = GET_MODE (operands[2]);
8610 enum rtx_code rc = GET_CODE (operands[1]);
8611
8612 /* Note that operands[4] is the same as operands[1],
8613 but with VOIDmode as the result. */
8614 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8615 if (mode == CCFPmode || mode == CCFPEmode)
8616 rc = reverse_condition_maybe_unordered (rc);
8617 else
8618 rc = reverse_condition (rc);
8619 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8620 }
8621 [(set_attr "conds" "use")
8622 (set_attr "type" "multiple")
8623 (set_attr "length" "8")]
8624 )
8625
8626 (define_insn_and_split "*ior_scc"
8627 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8628 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8629 [(match_operand 2 "cc_register" "") (const_int 0)])
8630 (match_operand:SI 3 "s_register_operand" "0,?r")))]
8631 "TARGET_ARM"
8632 "@
8633 orr%d1\\t%0, %3, #1
8634 #"
8635 "&& reload_completed
8636 && REGNO (operands [0]) != REGNO (operands[3])"
8637 ;; && which_alternative == 1
8638 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8639 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8640 (cond_exec (match_dup 4) (set (match_dup 0)
8641 (ior:SI (match_dup 3) (const_int 1))))]
8642 {
8643 machine_mode mode = GET_MODE (operands[2]);
8644 enum rtx_code rc = GET_CODE (operands[1]);
8645
8646 /* Note that operands[4] is the same as operands[1],
8647 but with VOIDmode as the result. */
8648 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8649 if (mode == CCFPmode || mode == CCFPEmode)
8650 rc = reverse_condition_maybe_unordered (rc);
8651 else
8652 rc = reverse_condition (rc);
8653 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8654 }
8655 [(set_attr "conds" "use")
8656 (set_attr "length" "4,8")
8657 (set_attr "type" "logic_imm,multiple")]
8658 )
8659
8660 ; A series of splitters for the compare_scc pattern below. Note that
8661 ; order is important.
8662 (define_split
8663 [(set (match_operand:SI 0 "s_register_operand" "")
8664 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8665 (const_int 0)))
8666 (clobber (reg:CC CC_REGNUM))]
8667 "TARGET_32BIT && reload_completed"
8668 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8669
8670 (define_split
8671 [(set (match_operand:SI 0 "s_register_operand" "")
8672 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8673 (const_int 0)))
8674 (clobber (reg:CC CC_REGNUM))]
8675 "TARGET_32BIT && reload_completed"
8676 [(set (match_dup 0) (not:SI (match_dup 1)))
8677 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8678
8679 (define_split
8680 [(set (match_operand:SI 0 "s_register_operand" "")
8681 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8682 (const_int 0)))
8683 (clobber (reg:CC CC_REGNUM))]
8684 "arm_arch5t && TARGET_32BIT"
8685 [(set (match_dup 0) (clz:SI (match_dup 1)))
8686 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8687 )
8688
8689 (define_split
8690 [(set (match_operand:SI 0 "s_register_operand" "")
8691 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8692 (const_int 0)))
8693 (clobber (reg:CC CC_REGNUM))]
8694 "TARGET_32BIT && reload_completed"
8695 [(parallel
8696 [(set (reg:CC CC_REGNUM)
8697 (compare:CC (const_int 1) (match_dup 1)))
8698 (set (match_dup 0)
8699 (minus:SI (const_int 1) (match_dup 1)))])
8700 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
8701 (set (match_dup 0) (const_int 0)))])
8702
8703 (define_split
8704 [(set (match_operand:SI 0 "s_register_operand" "")
8705 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8706 (match_operand:SI 2 "const_int_operand" "")))
8707 (clobber (reg:CC CC_REGNUM))]
8708 "TARGET_32BIT && reload_completed"
8709 [(parallel
8710 [(set (reg:CC CC_REGNUM)
8711 (compare:CC (match_dup 1) (match_dup 2)))
8712 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8713 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8714 (set (match_dup 0) (const_int 1)))]
8715 {
8716 operands[3] = gen_int_mode (-INTVAL (operands[2]), SImode);
8717 })
8718
8719 (define_split
8720 [(set (match_operand:SI 0 "s_register_operand" "")
8721 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8722 (match_operand:SI 2 "arm_add_operand" "")))
8723 (clobber (reg:CC CC_REGNUM))]
8724 "TARGET_32BIT && reload_completed"
8725 [(parallel
8726 [(set (reg:CC_NOOV CC_REGNUM)
8727 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8728 (const_int 0)))
8729 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8730 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8731 (set (match_dup 0) (const_int 1)))])
8732
8733 (define_insn_and_split "*compare_scc"
8734 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8735 (match_operator:SI 1 "arm_comparison_operator"
8736 [(match_operand:SI 2 "s_register_operand" "r,r")
8737 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8738 (clobber (reg:CC CC_REGNUM))]
8739 "TARGET_32BIT"
8740 "#"
8741 "&& reload_completed"
8742 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8743 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8744 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8745 {
8746 rtx tmp1;
8747 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8748 operands[2], operands[3]);
8749 enum rtx_code rc = GET_CODE (operands[1]);
8750
8751 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
8752
8753 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8754 if (mode == CCFPmode || mode == CCFPEmode)
8755 rc = reverse_condition_maybe_unordered (rc);
8756 else
8757 rc = reverse_condition (rc);
8758 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8759 }
8760 [(set_attr "type" "multiple")]
8761 )
8762
8763 ;; Attempt to improve the sequence generated by the compare_scc splitters
8764 ;; not to use conditional execution.
8765
8766 ;; Rd = (eq (reg1) (const_int0)) // ARMv5
8767 ;; clz Rd, reg1
8768 ;; lsr Rd, Rd, #5
8769 (define_peephole2
8770 [(set (reg:CC CC_REGNUM)
8771 (compare:CC (match_operand:SI 1 "register_operand" "")
8772 (const_int 0)))
8773 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8774 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8775 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8776 (set (match_dup 0) (const_int 1)))]
8777 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8778 [(set (match_dup 0) (clz:SI (match_dup 1)))
8779 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8780 )
8781
8782 ;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8783 ;; negs Rd, reg1
8784 ;; adc Rd, Rd, reg1
8785 (define_peephole2
8786 [(set (reg:CC CC_REGNUM)
8787 (compare:CC (match_operand:SI 1 "register_operand" "")
8788 (const_int 0)))
8789 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8790 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8791 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8792 (set (match_dup 0) (const_int 1)))
8793 (match_scratch:SI 2 "r")]
8794 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8795 [(parallel
8796 [(set (reg:CC CC_REGNUM)
8797 (compare:CC (const_int 0) (match_dup 1)))
8798 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8799 (set (match_dup 0)
8800 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8801 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8802 )
8803
8804 ;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
8805 ;; sub Rd, Reg1, reg2
8806 ;; clz Rd, Rd
8807 ;; lsr Rd, Rd, #5
8808 (define_peephole2
8809 [(set (reg:CC CC_REGNUM)
8810 (compare:CC (match_operand:SI 1 "register_operand" "")
8811 (match_operand:SI 2 "arm_rhs_operand" "")))
8812 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8813 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8814 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8815 (set (match_dup 0) (const_int 1)))]
8816 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8817 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
8818 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8819 (set (match_dup 0) (clz:SI (match_dup 0)))
8820 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8821 )
8822
8823
8824 ;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
8825 ;; sub T1, Reg1, reg2
8826 ;; negs Rd, T1
8827 ;; adc Rd, Rd, T1
8828 (define_peephole2
8829 [(set (reg:CC CC_REGNUM)
8830 (compare:CC (match_operand:SI 1 "register_operand" "")
8831 (match_operand:SI 2 "arm_rhs_operand" "")))
8832 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8833 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8834 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8835 (set (match_dup 0) (const_int 1)))
8836 (match_scratch:SI 3 "r")]
8837 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8838 [(set (match_dup 3) (match_dup 4))
8839 (parallel
8840 [(set (reg:CC CC_REGNUM)
8841 (compare:CC (const_int 0) (match_dup 3)))
8842 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8843 (set (match_dup 0)
8844 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8845 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8846 "
8847 if (CONST_INT_P (operands[2]))
8848 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8849 else
8850 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8851 ")
8852
8853 (define_insn "*cond_move"
8854 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8855 (if_then_else:SI (match_operator 3 "equality_operator"
8856 [(match_operator 4 "arm_comparison_operator"
8857 [(match_operand 5 "cc_register" "") (const_int 0)])
8858 (const_int 0)])
8859 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8860 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8861 "TARGET_ARM"
8862 "*
8863 if (GET_CODE (operands[3]) == NE)
8864 {
8865 if (which_alternative != 1)
8866 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8867 if (which_alternative != 0)
8868 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8869 return \"\";
8870 }
8871 if (which_alternative != 0)
8872 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8873 if (which_alternative != 1)
8874 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8875 return \"\";
8876 "
8877 [(set_attr "conds" "use")
8878 (set_attr_alternative "type"
8879 [(if_then_else (match_operand 2 "const_int_operand" "")
8880 (const_string "mov_imm")
8881 (const_string "mov_reg"))
8882 (if_then_else (match_operand 1 "const_int_operand" "")
8883 (const_string "mov_imm")
8884 (const_string "mov_reg"))
8885 (const_string "multiple")])
8886 (set_attr "length" "4,4,8")]
8887 )
8888
8889 (define_insn "*cond_arith"
8890 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8891 (match_operator:SI 5 "shiftable_operator"
8892 [(match_operator:SI 4 "arm_comparison_operator"
8893 [(match_operand:SI 2 "s_register_operand" "r,r")
8894 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8895 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8896 (clobber (reg:CC CC_REGNUM))]
8897 "TARGET_ARM"
8898 "*
8899 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8900 return \"%i5\\t%0, %1, %2, lsr #31\";
8901
8902 output_asm_insn (\"cmp\\t%2, %3\", operands);
8903 if (GET_CODE (operands[5]) == AND)
8904 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8905 else if (GET_CODE (operands[5]) == MINUS)
8906 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8907 else if (which_alternative != 0)
8908 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8909 return \"%i5%d4\\t%0, %1, #1\";
8910 "
8911 [(set_attr "conds" "clob")
8912 (set_attr "length" "12")
8913 (set_attr "type" "multiple")]
8914 )
8915
8916 (define_insn "*cond_sub"
8917 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8918 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8919 (match_operator:SI 4 "arm_comparison_operator"
8920 [(match_operand:SI 2 "s_register_operand" "r,r")
8921 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8922 (clobber (reg:CC CC_REGNUM))]
8923 "TARGET_ARM"
8924 "*
8925 output_asm_insn (\"cmp\\t%2, %3\", operands);
8926 if (which_alternative != 0)
8927 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8928 return \"sub%d4\\t%0, %1, #1\";
8929 "
8930 [(set_attr "conds" "clob")
8931 (set_attr "length" "8,12")
8932 (set_attr "type" "multiple")]
8933 )
8934
8935 (define_insn "*cmp_ite0"
8936 [(set (match_operand 6 "dominant_cc_register" "")
8937 (compare
8938 (if_then_else:SI
8939 (match_operator 4 "arm_comparison_operator"
8940 [(match_operand:SI 0 "s_register_operand"
8941 "l,l,l,r,r,r,r,r,r")
8942 (match_operand:SI 1 "arm_add_operand"
8943 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
8944 (match_operator:SI 5 "arm_comparison_operator"
8945 [(match_operand:SI 2 "s_register_operand"
8946 "l,r,r,l,l,r,r,r,r")
8947 (match_operand:SI 3 "arm_add_operand"
8948 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
8949 (const_int 0))
8950 (const_int 0)))]
8951 "TARGET_32BIT"
8952 "*
8953 {
8954 static const char * const cmp1[NUM_OF_COND_CMP][2] =
8955 {
8956 {\"cmp%d5\\t%0, %1\",
8957 \"cmp%d4\\t%2, %3\"},
8958 {\"cmn%d5\\t%0, #%n1\",
8959 \"cmp%d4\\t%2, %3\"},
8960 {\"cmp%d5\\t%0, %1\",
8961 \"cmn%d4\\t%2, #%n3\"},
8962 {\"cmn%d5\\t%0, #%n1\",
8963 \"cmn%d4\\t%2, #%n3\"}
8964 };
8965 static const char * const cmp2[NUM_OF_COND_CMP][2] =
8966 {
8967 {\"cmp\\t%2, %3\",
8968 \"cmp\\t%0, %1\"},
8969 {\"cmp\\t%2, %3\",
8970 \"cmn\\t%0, #%n1\"},
8971 {\"cmn\\t%2, #%n3\",
8972 \"cmp\\t%0, %1\"},
8973 {\"cmn\\t%2, #%n3\",
8974 \"cmn\\t%0, #%n1\"}
8975 };
8976 static const char * const ite[2] =
8977 {
8978 \"it\\t%d5\",
8979 \"it\\t%d4\"
8980 };
8981 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8982 CMP_CMP, CMN_CMP, CMP_CMP,
8983 CMN_CMP, CMP_CMN, CMN_CMN};
8984 int swap =
8985 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8986
8987 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8988 if (TARGET_THUMB2) {
8989 output_asm_insn (ite[swap], operands);
8990 }
8991 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8992 return \"\";
8993 }"
8994 [(set_attr "conds" "set")
8995 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8996 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
8997 (set_attr "type" "multiple")
8998 (set_attr_alternative "length"
8999 [(const_int 6)
9000 (const_int 8)
9001 (const_int 8)
9002 (const_int 8)
9003 (const_int 8)
9004 (if_then_else (eq_attr "is_thumb" "no")
9005 (const_int 8)
9006 (const_int 10))
9007 (if_then_else (eq_attr "is_thumb" "no")
9008 (const_int 8)
9009 (const_int 10))
9010 (if_then_else (eq_attr "is_thumb" "no")
9011 (const_int 8)
9012 (const_int 10))
9013 (if_then_else (eq_attr "is_thumb" "no")
9014 (const_int 8)
9015 (const_int 10))])]
9016 )
9017
9018 (define_insn "*cmp_ite1"
9019 [(set (match_operand 6 "dominant_cc_register" "")
9020 (compare
9021 (if_then_else:SI
9022 (match_operator 4 "arm_comparison_operator"
9023 [(match_operand:SI 0 "s_register_operand"
9024 "l,l,l,r,r,r,r,r,r")
9025 (match_operand:SI 1 "arm_add_operand"
9026 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9027 (match_operator:SI 5 "arm_comparison_operator"
9028 [(match_operand:SI 2 "s_register_operand"
9029 "l,r,r,l,l,r,r,r,r")
9030 (match_operand:SI 3 "arm_add_operand"
9031 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9032 (const_int 1))
9033 (const_int 0)))]
9034 "TARGET_32BIT"
9035 "*
9036 {
9037 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9038 {
9039 {\"cmp\\t%0, %1\",
9040 \"cmp\\t%2, %3\"},
9041 {\"cmn\\t%0, #%n1\",
9042 \"cmp\\t%2, %3\"},
9043 {\"cmp\\t%0, %1\",
9044 \"cmn\\t%2, #%n3\"},
9045 {\"cmn\\t%0, #%n1\",
9046 \"cmn\\t%2, #%n3\"}
9047 };
9048 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9049 {
9050 {\"cmp%d4\\t%2, %3\",
9051 \"cmp%D5\\t%0, %1\"},
9052 {\"cmp%d4\\t%2, %3\",
9053 \"cmn%D5\\t%0, #%n1\"},
9054 {\"cmn%d4\\t%2, #%n3\",
9055 \"cmp%D5\\t%0, %1\"},
9056 {\"cmn%d4\\t%2, #%n3\",
9057 \"cmn%D5\\t%0, #%n1\"}
9058 };
9059 static const char * const ite[2] =
9060 {
9061 \"it\\t%d4\",
9062 \"it\\t%D5\"
9063 };
9064 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9065 CMP_CMP, CMN_CMP, CMP_CMP,
9066 CMN_CMP, CMP_CMN, CMN_CMN};
9067 int swap =
9068 comparison_dominates_p (GET_CODE (operands[5]),
9069 reverse_condition (GET_CODE (operands[4])));
9070
9071 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9072 if (TARGET_THUMB2) {
9073 output_asm_insn (ite[swap], operands);
9074 }
9075 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9076 return \"\";
9077 }"
9078 [(set_attr "conds" "set")
9079 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9080 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9081 (set_attr_alternative "length"
9082 [(const_int 6)
9083 (const_int 8)
9084 (const_int 8)
9085 (const_int 8)
9086 (const_int 8)
9087 (if_then_else (eq_attr "is_thumb" "no")
9088 (const_int 8)
9089 (const_int 10))
9090 (if_then_else (eq_attr "is_thumb" "no")
9091 (const_int 8)
9092 (const_int 10))
9093 (if_then_else (eq_attr "is_thumb" "no")
9094 (const_int 8)
9095 (const_int 10))
9096 (if_then_else (eq_attr "is_thumb" "no")
9097 (const_int 8)
9098 (const_int 10))])
9099 (set_attr "type" "multiple")]
9100 )
9101
9102 (define_insn "*cmp_and"
9103 [(set (match_operand 6 "dominant_cc_register" "")
9104 (compare
9105 (and:SI
9106 (match_operator 4 "arm_comparison_operator"
9107 [(match_operand:SI 0 "s_register_operand"
9108 "l,l,l,r,r,r,r,r,r,r")
9109 (match_operand:SI 1 "arm_add_operand"
9110 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
9111 (match_operator:SI 5 "arm_comparison_operator"
9112 [(match_operand:SI 2 "s_register_operand"
9113 "l,r,r,l,l,r,r,r,r,r")
9114 (match_operand:SI 3 "arm_add_operand"
9115 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
9116 (const_int 0)))]
9117 "TARGET_32BIT"
9118 "*
9119 {
9120 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9121 {
9122 {\"cmp%d5\\t%0, %1\",
9123 \"cmp%d4\\t%2, %3\"},
9124 {\"cmn%d5\\t%0, #%n1\",
9125 \"cmp%d4\\t%2, %3\"},
9126 {\"cmp%d5\\t%0, %1\",
9127 \"cmn%d4\\t%2, #%n3\"},
9128 {\"cmn%d5\\t%0, #%n1\",
9129 \"cmn%d4\\t%2, #%n3\"}
9130 };
9131 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9132 {
9133 {\"cmp\\t%2, %3\",
9134 \"cmp\\t%0, %1\"},
9135 {\"cmp\\t%2, %3\",
9136 \"cmn\\t%0, #%n1\"},
9137 {\"cmn\\t%2, #%n3\",
9138 \"cmp\\t%0, %1\"},
9139 {\"cmn\\t%2, #%n3\",
9140 \"cmn\\t%0, #%n1\"}
9141 };
9142 static const char *const ite[2] =
9143 {
9144 \"it\\t%d5\",
9145 \"it\\t%d4\"
9146 };
9147 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9148 CMP_CMP, CMN_CMP, CMP_CMP,
9149 CMP_CMP, CMN_CMP, CMP_CMN,
9150 CMN_CMN};
9151 int swap =
9152 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9153
9154 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9155 if (TARGET_THUMB2) {
9156 output_asm_insn (ite[swap], operands);
9157 }
9158 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9159 return \"\";
9160 }"
9161 [(set_attr "conds" "set")
9162 (set_attr "predicable" "no")
9163 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9164 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
9165 (set_attr_alternative "length"
9166 [(const_int 6)
9167 (const_int 8)
9168 (const_int 8)
9169 (const_int 8)
9170 (const_int 8)
9171 (const_int 6)
9172 (if_then_else (eq_attr "is_thumb" "no")
9173 (const_int 8)
9174 (const_int 10))
9175 (if_then_else (eq_attr "is_thumb" "no")
9176 (const_int 8)
9177 (const_int 10))
9178 (if_then_else (eq_attr "is_thumb" "no")
9179 (const_int 8)
9180 (const_int 10))
9181 (if_then_else (eq_attr "is_thumb" "no")
9182 (const_int 8)
9183 (const_int 10))])
9184 (set_attr "type" "multiple")]
9185 )
9186
9187 (define_insn "*cmp_ior"
9188 [(set (match_operand 6 "dominant_cc_register" "")
9189 (compare
9190 (ior:SI
9191 (match_operator 4 "arm_comparison_operator"
9192 [(match_operand:SI 0 "s_register_operand"
9193 "l,l,l,r,r,r,r,r,r,r")
9194 (match_operand:SI 1 "arm_add_operand"
9195 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
9196 (match_operator:SI 5 "arm_comparison_operator"
9197 [(match_operand:SI 2 "s_register_operand"
9198 "l,r,r,l,l,r,r,r,r,r")
9199 (match_operand:SI 3 "arm_add_operand"
9200 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
9201 (const_int 0)))]
9202 "TARGET_32BIT"
9203 "*
9204 {
9205 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9206 {
9207 {\"cmp\\t%0, %1\",
9208 \"cmp\\t%2, %3\"},
9209 {\"cmn\\t%0, #%n1\",
9210 \"cmp\\t%2, %3\"},
9211 {\"cmp\\t%0, %1\",
9212 \"cmn\\t%2, #%n3\"},
9213 {\"cmn\\t%0, #%n1\",
9214 \"cmn\\t%2, #%n3\"}
9215 };
9216 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9217 {
9218 {\"cmp%D4\\t%2, %3\",
9219 \"cmp%D5\\t%0, %1\"},
9220 {\"cmp%D4\\t%2, %3\",
9221 \"cmn%D5\\t%0, #%n1\"},
9222 {\"cmn%D4\\t%2, #%n3\",
9223 \"cmp%D5\\t%0, %1\"},
9224 {\"cmn%D4\\t%2, #%n3\",
9225 \"cmn%D5\\t%0, #%n1\"}
9226 };
9227 static const char *const ite[2] =
9228 {
9229 \"it\\t%D4\",
9230 \"it\\t%D5\"
9231 };
9232 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9233 CMP_CMP, CMN_CMP, CMP_CMP,
9234 CMP_CMP, CMN_CMP, CMP_CMN,
9235 CMN_CMN};
9236 int swap =
9237 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9238
9239 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9240 if (TARGET_THUMB2) {
9241 output_asm_insn (ite[swap], operands);
9242 }
9243 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9244 return \"\";
9245 }
9246 "
9247 [(set_attr "conds" "set")
9248 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9249 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
9250 (set_attr_alternative "length"
9251 [(const_int 6)
9252 (const_int 8)
9253 (const_int 8)
9254 (const_int 8)
9255 (const_int 8)
9256 (const_int 6)
9257 (if_then_else (eq_attr "is_thumb" "no")
9258 (const_int 8)
9259 (const_int 10))
9260 (if_then_else (eq_attr "is_thumb" "no")
9261 (const_int 8)
9262 (const_int 10))
9263 (if_then_else (eq_attr "is_thumb" "no")
9264 (const_int 8)
9265 (const_int 10))
9266 (if_then_else (eq_attr "is_thumb" "no")
9267 (const_int 8)
9268 (const_int 10))])
9269 (set_attr "type" "multiple")]
9270 )
9271
9272 (define_insn_and_split "*ior_scc_scc"
9273 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9274 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9275 [(match_operand:SI 1 "s_register_operand" "l,r")
9276 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9277 (match_operator:SI 6 "arm_comparison_operator"
9278 [(match_operand:SI 4 "s_register_operand" "l,r")
9279 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9280 (clobber (reg:CC CC_REGNUM))]
9281 "TARGET_32BIT
9282 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9283 != CCmode)"
9284 "#"
9285 "TARGET_32BIT && reload_completed"
9286 [(set (match_dup 7)
9287 (compare
9288 (ior:SI
9289 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9290 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9291 (const_int 0)))
9292 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9293 "operands[7]
9294 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9295 DOM_CC_X_OR_Y),
9296 CC_REGNUM);"
9297 [(set_attr "conds" "clob")
9298 (set_attr "enabled_for_short_it" "yes,no")
9299 (set_attr "length" "16")
9300 (set_attr "type" "multiple")]
9301 )
9302
9303 ; If the above pattern is followed by a CMP insn, then the compare is
9304 ; redundant, since we can rework the conditional instruction that follows.
9305 (define_insn_and_split "*ior_scc_scc_cmp"
9306 [(set (match_operand 0 "dominant_cc_register" "")
9307 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9308 [(match_operand:SI 1 "s_register_operand" "l,r")
9309 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9310 (match_operator:SI 6 "arm_comparison_operator"
9311 [(match_operand:SI 4 "s_register_operand" "l,r")
9312 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9313 (const_int 0)))
9314 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9315 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9316 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9317 "TARGET_32BIT"
9318 "#"
9319 "TARGET_32BIT && reload_completed"
9320 [(set (match_dup 0)
9321 (compare
9322 (ior:SI
9323 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9324 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9325 (const_int 0)))
9326 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9327 ""
9328 [(set_attr "conds" "set")
9329 (set_attr "enabled_for_short_it" "yes,no")
9330 (set_attr "length" "16")
9331 (set_attr "type" "multiple")]
9332 )
9333
9334 (define_insn_and_split "*and_scc_scc"
9335 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9336 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9337 [(match_operand:SI 1 "s_register_operand" "l,r")
9338 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9339 (match_operator:SI 6 "arm_comparison_operator"
9340 [(match_operand:SI 4 "s_register_operand" "l,r")
9341 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9342 (clobber (reg:CC CC_REGNUM))]
9343 "TARGET_32BIT
9344 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9345 != CCmode)"
9346 "#"
9347 "TARGET_32BIT && reload_completed
9348 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9349 != CCmode)"
9350 [(set (match_dup 7)
9351 (compare
9352 (and:SI
9353 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9354 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9355 (const_int 0)))
9356 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9357 "operands[7]
9358 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9359 DOM_CC_X_AND_Y),
9360 CC_REGNUM);"
9361 [(set_attr "conds" "clob")
9362 (set_attr "enabled_for_short_it" "yes,no")
9363 (set_attr "length" "16")
9364 (set_attr "type" "multiple")]
9365 )
9366
9367 ; If the above pattern is followed by a CMP insn, then the compare is
9368 ; redundant, since we can rework the conditional instruction that follows.
9369 (define_insn_and_split "*and_scc_scc_cmp"
9370 [(set (match_operand 0 "dominant_cc_register" "")
9371 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9372 [(match_operand:SI 1 "s_register_operand" "l,r")
9373 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9374 (match_operator:SI 6 "arm_comparison_operator"
9375 [(match_operand:SI 4 "s_register_operand" "l,r")
9376 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9377 (const_int 0)))
9378 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9379 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9380 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9381 "TARGET_32BIT"
9382 "#"
9383 "TARGET_32BIT && reload_completed"
9384 [(set (match_dup 0)
9385 (compare
9386 (and:SI
9387 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9388 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9389 (const_int 0)))
9390 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9391 ""
9392 [(set_attr "conds" "set")
9393 (set_attr "enabled_for_short_it" "yes,no")
9394 (set_attr "length" "16")
9395 (set_attr "type" "multiple")]
9396 )
9397
9398 ;; If there is no dominance in the comparison, then we can still save an
9399 ;; instruction in the AND case, since we can know that the second compare
9400 ;; need only zero the value if false (if true, then the value is already
9401 ;; correct).
9402 (define_insn_and_split "*and_scc_scc_nodom"
9403 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
9404 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9405 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9406 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9407 (match_operator:SI 6 "arm_comparison_operator"
9408 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9409 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9410 (clobber (reg:CC CC_REGNUM))]
9411 "TARGET_32BIT
9412 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9413 == CCmode)"
9414 "#"
9415 "TARGET_32BIT && reload_completed"
9416 [(parallel [(set (match_dup 0)
9417 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9418 (clobber (reg:CC CC_REGNUM))])
9419 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9420 (set (match_dup 0)
9421 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9422 (match_dup 0)
9423 (const_int 0)))]
9424 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9425 operands[4], operands[5]),
9426 CC_REGNUM);
9427 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9428 operands[5]);"
9429 [(set_attr "conds" "clob")
9430 (set_attr "length" "20")
9431 (set_attr "type" "multiple")]
9432 )
9433
9434 (define_split
9435 [(set (reg:CC_NOOV CC_REGNUM)
9436 (compare:CC_NOOV (ior:SI
9437 (and:SI (match_operand:SI 0 "s_register_operand" "")
9438 (const_int 1))
9439 (match_operator:SI 1 "arm_comparison_operator"
9440 [(match_operand:SI 2 "s_register_operand" "")
9441 (match_operand:SI 3 "arm_add_operand" "")]))
9442 (const_int 0)))
9443 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9444 "TARGET_ARM"
9445 [(set (match_dup 4)
9446 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9447 (match_dup 0)))
9448 (set (reg:CC_NOOV CC_REGNUM)
9449 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9450 (const_int 0)))]
9451 "")
9452
9453 (define_split
9454 [(set (reg:CC_NOOV CC_REGNUM)
9455 (compare:CC_NOOV (ior:SI
9456 (match_operator:SI 1 "arm_comparison_operator"
9457 [(match_operand:SI 2 "s_register_operand" "")
9458 (match_operand:SI 3 "arm_add_operand" "")])
9459 (and:SI (match_operand:SI 0 "s_register_operand" "")
9460 (const_int 1)))
9461 (const_int 0)))
9462 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9463 "TARGET_ARM"
9464 [(set (match_dup 4)
9465 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9466 (match_dup 0)))
9467 (set (reg:CC_NOOV CC_REGNUM)
9468 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9469 (const_int 0)))]
9470 "")
9471 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9472
9473 (define_insn_and_split "*negscc"
9474 [(set (match_operand:SI 0 "s_register_operand" "=r")
9475 (neg:SI (match_operator 3 "arm_comparison_operator"
9476 [(match_operand:SI 1 "s_register_operand" "r")
9477 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9478 (clobber (reg:CC CC_REGNUM))]
9479 "TARGET_ARM"
9480 "#"
9481 "&& reload_completed"
9482 [(const_int 0)]
9483 {
9484 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
9485
9486 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9487 {
9488 /* Emit mov\\t%0, %1, asr #31 */
9489 emit_insn (gen_rtx_SET (operands[0],
9490 gen_rtx_ASHIFTRT (SImode,
9491 operands[1],
9492 GEN_INT (31))));
9493 DONE;
9494 }
9495 else if (GET_CODE (operands[3]) == NE)
9496 {
9497 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9498 if (CONST_INT_P (operands[2]))
9499 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9500 gen_int_mode (-INTVAL (operands[2]),
9501 SImode)));
9502 else
9503 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9504
9505 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9506 gen_rtx_NE (SImode,
9507 cc_reg,
9508 const0_rtx),
9509 gen_rtx_SET (operands[0],
9510 GEN_INT (~0))));
9511 DONE;
9512 }
9513 else
9514 {
9515 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9516 emit_insn (gen_rtx_SET (cc_reg,
9517 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9518 enum rtx_code rc = GET_CODE (operands[3]);
9519
9520 rc = reverse_condition (rc);
9521 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9522 gen_rtx_fmt_ee (rc,
9523 VOIDmode,
9524 cc_reg,
9525 const0_rtx),
9526 gen_rtx_SET (operands[0], const0_rtx)));
9527 rc = GET_CODE (operands[3]);
9528 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9529 gen_rtx_fmt_ee (rc,
9530 VOIDmode,
9531 cc_reg,
9532 const0_rtx),
9533 gen_rtx_SET (operands[0],
9534 GEN_INT (~0))));
9535 DONE;
9536 }
9537 FAIL;
9538 }
9539 [(set_attr "conds" "clob")
9540 (set_attr "length" "12")
9541 (set_attr "type" "multiple")]
9542 )
9543
9544 (define_insn_and_split "movcond_addsi"
9545 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9546 (if_then_else:SI
9547 (match_operator 5 "comparison_operator"
9548 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9549 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9550 (const_int 0)])
9551 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9552 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9553 (clobber (reg:CC CC_REGNUM))]
9554 "TARGET_32BIT"
9555 "#"
9556 "&& reload_completed"
9557 [(set (reg:CC_NOOV CC_REGNUM)
9558 (compare:CC_NOOV
9559 (plus:SI (match_dup 3)
9560 (match_dup 4))
9561 (const_int 0)))
9562 (set (match_dup 0) (match_dup 1))
9563 (cond_exec (match_dup 6)
9564 (set (match_dup 0) (match_dup 2)))]
9565 "
9566 {
9567 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
9568 operands[3], operands[4]);
9569 enum rtx_code rc = GET_CODE (operands[5]);
9570 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9571 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
9572 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
9573 rc = reverse_condition (rc);
9574 else
9575 std::swap (operands[1], operands[2]);
9576
9577 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9578 }
9579 "
9580 [(set_attr "conds" "clob")
9581 (set_attr "enabled_for_short_it" "no,yes,yes")
9582 (set_attr "type" "multiple")]
9583 )
9584
9585 (define_insn "movcond"
9586 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9587 (if_then_else:SI
9588 (match_operator 5 "arm_comparison_operator"
9589 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9590 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9591 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9592 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9593 (clobber (reg:CC CC_REGNUM))]
9594 "TARGET_ARM"
9595 "*
9596 if (GET_CODE (operands[5]) == LT
9597 && (operands[4] == const0_rtx))
9598 {
9599 if (which_alternative != 1 && REG_P (operands[1]))
9600 {
9601 if (operands[2] == const0_rtx)
9602 return \"and\\t%0, %1, %3, asr #31\";
9603 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9604 }
9605 else if (which_alternative != 0 && REG_P (operands[2]))
9606 {
9607 if (operands[1] == const0_rtx)
9608 return \"bic\\t%0, %2, %3, asr #31\";
9609 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9610 }
9611 /* The only case that falls through to here is when both ops 1 & 2
9612 are constants. */
9613 }
9614
9615 if (GET_CODE (operands[5]) == GE
9616 && (operands[4] == const0_rtx))
9617 {
9618 if (which_alternative != 1 && REG_P (operands[1]))
9619 {
9620 if (operands[2] == const0_rtx)
9621 return \"bic\\t%0, %1, %3, asr #31\";
9622 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9623 }
9624 else if (which_alternative != 0 && REG_P (operands[2]))
9625 {
9626 if (operands[1] == const0_rtx)
9627 return \"and\\t%0, %2, %3, asr #31\";
9628 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9629 }
9630 /* The only case that falls through to here is when both ops 1 & 2
9631 are constants. */
9632 }
9633 if (CONST_INT_P (operands[4])
9634 && !const_ok_for_arm (INTVAL (operands[4])))
9635 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9636 else
9637 output_asm_insn (\"cmp\\t%3, %4\", operands);
9638 if (which_alternative != 0)
9639 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9640 if (which_alternative != 1)
9641 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9642 return \"\";
9643 "
9644 [(set_attr "conds" "clob")
9645 (set_attr "length" "8,8,12")
9646 (set_attr "type" "multiple")]
9647 )
9648
9649 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9650
9651 (define_insn "*ifcompare_plus_move"
9652 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9653 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9654 [(match_operand:SI 4 "s_register_operand" "r,r")
9655 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9656 (plus:SI
9657 (match_operand:SI 2 "s_register_operand" "r,r")
9658 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9659 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9660 (clobber (reg:CC CC_REGNUM))]
9661 "TARGET_ARM"
9662 "#"
9663 [(set_attr "conds" "clob")
9664 (set_attr "length" "8,12")
9665 (set_attr "type" "multiple")]
9666 )
9667
9668 (define_insn "*if_plus_move"
9669 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9670 (if_then_else:SI
9671 (match_operator 4 "arm_comparison_operator"
9672 [(match_operand 5 "cc_register" "") (const_int 0)])
9673 (plus:SI
9674 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9675 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9676 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9677 "TARGET_ARM"
9678 "@
9679 add%d4\\t%0, %2, %3
9680 sub%d4\\t%0, %2, #%n3
9681 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9682 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9683 [(set_attr "conds" "use")
9684 (set_attr "length" "4,4,8,8")
9685 (set_attr_alternative "type"
9686 [(if_then_else (match_operand 3 "const_int_operand" "")
9687 (const_string "alu_imm" )
9688 (const_string "alu_sreg"))
9689 (const_string "alu_imm")
9690 (const_string "multiple")
9691 (const_string "multiple")])]
9692 )
9693
9694 (define_insn "*ifcompare_move_plus"
9695 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9696 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9697 [(match_operand:SI 4 "s_register_operand" "r,r")
9698 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9699 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9700 (plus:SI
9701 (match_operand:SI 2 "s_register_operand" "r,r")
9702 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9703 (clobber (reg:CC CC_REGNUM))]
9704 "TARGET_ARM"
9705 "#"
9706 [(set_attr "conds" "clob")
9707 (set_attr "length" "8,12")
9708 (set_attr "type" "multiple")]
9709 )
9710
9711 (define_insn "*if_move_plus"
9712 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9713 (if_then_else:SI
9714 (match_operator 4 "arm_comparison_operator"
9715 [(match_operand 5 "cc_register" "") (const_int 0)])
9716 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9717 (plus:SI
9718 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9719 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9720 "TARGET_ARM"
9721 "@
9722 add%D4\\t%0, %2, %3
9723 sub%D4\\t%0, %2, #%n3
9724 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9725 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9726 [(set_attr "conds" "use")
9727 (set_attr "length" "4,4,8,8")
9728 (set_attr_alternative "type"
9729 [(if_then_else (match_operand 3 "const_int_operand" "")
9730 (const_string "alu_imm" )
9731 (const_string "alu_sreg"))
9732 (const_string "alu_imm")
9733 (const_string "multiple")
9734 (const_string "multiple")])]
9735 )
9736
9737 (define_insn "*ifcompare_arith_arith"
9738 [(set (match_operand:SI 0 "s_register_operand" "=r")
9739 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9740 [(match_operand:SI 5 "s_register_operand" "r")
9741 (match_operand:SI 6 "arm_add_operand" "rIL")])
9742 (match_operator:SI 8 "shiftable_operator"
9743 [(match_operand:SI 1 "s_register_operand" "r")
9744 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9745 (match_operator:SI 7 "shiftable_operator"
9746 [(match_operand:SI 3 "s_register_operand" "r")
9747 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9748 (clobber (reg:CC CC_REGNUM))]
9749 "TARGET_ARM"
9750 "#"
9751 [(set_attr "conds" "clob")
9752 (set_attr "length" "12")
9753 (set_attr "type" "multiple")]
9754 )
9755
9756 (define_insn "*if_arith_arith"
9757 [(set (match_operand:SI 0 "s_register_operand" "=r")
9758 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9759 [(match_operand 8 "cc_register" "") (const_int 0)])
9760 (match_operator:SI 6 "shiftable_operator"
9761 [(match_operand:SI 1 "s_register_operand" "r")
9762 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9763 (match_operator:SI 7 "shiftable_operator"
9764 [(match_operand:SI 3 "s_register_operand" "r")
9765 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9766 "TARGET_ARM"
9767 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9768 [(set_attr "conds" "use")
9769 (set_attr "length" "8")
9770 (set_attr "type" "multiple")]
9771 )
9772
9773 (define_insn "*ifcompare_arith_move"
9774 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9775 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9776 [(match_operand:SI 2 "s_register_operand" "r,r")
9777 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9778 (match_operator:SI 7 "shiftable_operator"
9779 [(match_operand:SI 4 "s_register_operand" "r,r")
9780 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9781 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9782 (clobber (reg:CC CC_REGNUM))]
9783 "TARGET_ARM"
9784 "*
9785 /* If we have an operation where (op x 0) is the identity operation and
9786 the conditional operator is LT or GE and we are comparing against zero and
9787 everything is in registers then we can do this in two instructions. */
9788 if (operands[3] == const0_rtx
9789 && GET_CODE (operands[7]) != AND
9790 && REG_P (operands[5])
9791 && REG_P (operands[1])
9792 && REGNO (operands[1]) == REGNO (operands[4])
9793 && REGNO (operands[4]) != REGNO (operands[0]))
9794 {
9795 if (GET_CODE (operands[6]) == LT)
9796 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9797 else if (GET_CODE (operands[6]) == GE)
9798 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9799 }
9800 if (CONST_INT_P (operands[3])
9801 && !const_ok_for_arm (INTVAL (operands[3])))
9802 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9803 else
9804 output_asm_insn (\"cmp\\t%2, %3\", operands);
9805 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9806 if (which_alternative != 0)
9807 return \"mov%D6\\t%0, %1\";
9808 return \"\";
9809 "
9810 [(set_attr "conds" "clob")
9811 (set_attr "length" "8,12")
9812 (set_attr "type" "multiple")]
9813 )
9814
9815 (define_insn "*if_arith_move"
9816 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9817 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9818 [(match_operand 6 "cc_register" "") (const_int 0)])
9819 (match_operator:SI 5 "shiftable_operator"
9820 [(match_operand:SI 2 "s_register_operand" "r,r")
9821 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9822 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9823 "TARGET_ARM"
9824 "@
9825 %I5%d4\\t%0, %2, %3
9826 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9827 [(set_attr "conds" "use")
9828 (set_attr "length" "4,8")
9829 (set_attr_alternative "type"
9830 [(if_then_else (match_operand 3 "const_int_operand" "")
9831 (const_string "alu_shift_imm" )
9832 (const_string "alu_shift_reg"))
9833 (const_string "multiple")])]
9834 )
9835
9836 (define_insn "*ifcompare_move_arith"
9837 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9838 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9839 [(match_operand:SI 4 "s_register_operand" "r,r")
9840 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9841 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9842 (match_operator:SI 7 "shiftable_operator"
9843 [(match_operand:SI 2 "s_register_operand" "r,r")
9844 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9845 (clobber (reg:CC CC_REGNUM))]
9846 "TARGET_ARM"
9847 "*
9848 /* If we have an operation where (op x 0) is the identity operation and
9849 the conditional operator is LT or GE and we are comparing against zero and
9850 everything is in registers then we can do this in two instructions */
9851 if (operands[5] == const0_rtx
9852 && GET_CODE (operands[7]) != AND
9853 && REG_P (operands[3])
9854 && REG_P (operands[1])
9855 && REGNO (operands[1]) == REGNO (operands[2])
9856 && REGNO (operands[2]) != REGNO (operands[0]))
9857 {
9858 if (GET_CODE (operands[6]) == GE)
9859 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9860 else if (GET_CODE (operands[6]) == LT)
9861 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9862 }
9863
9864 if (CONST_INT_P (operands[5])
9865 && !const_ok_for_arm (INTVAL (operands[5])))
9866 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9867 else
9868 output_asm_insn (\"cmp\\t%4, %5\", operands);
9869
9870 if (which_alternative != 0)
9871 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9872 return \"%I7%D6\\t%0, %2, %3\";
9873 "
9874 [(set_attr "conds" "clob")
9875 (set_attr "length" "8,12")
9876 (set_attr "type" "multiple")]
9877 )
9878
9879 (define_insn "*if_move_arith"
9880 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9881 (if_then_else:SI
9882 (match_operator 4 "arm_comparison_operator"
9883 [(match_operand 6 "cc_register" "") (const_int 0)])
9884 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9885 (match_operator:SI 5 "shiftable_operator"
9886 [(match_operand:SI 2 "s_register_operand" "r,r")
9887 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9888 "TARGET_ARM"
9889 "@
9890 %I5%D4\\t%0, %2, %3
9891 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9892 [(set_attr "conds" "use")
9893 (set_attr "length" "4,8")
9894 (set_attr_alternative "type"
9895 [(if_then_else (match_operand 3 "const_int_operand" "")
9896 (const_string "alu_shift_imm" )
9897 (const_string "alu_shift_reg"))
9898 (const_string "multiple")])]
9899 )
9900
9901 (define_insn "*ifcompare_move_not"
9902 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9903 (if_then_else:SI
9904 (match_operator 5 "arm_comparison_operator"
9905 [(match_operand:SI 3 "s_register_operand" "r,r")
9906 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9907 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9908 (not:SI
9909 (match_operand:SI 2 "s_register_operand" "r,r"))))
9910 (clobber (reg:CC CC_REGNUM))]
9911 "TARGET_ARM"
9912 "#"
9913 [(set_attr "conds" "clob")
9914 (set_attr "length" "8,12")
9915 (set_attr "type" "multiple")]
9916 )
9917
9918 (define_insn "*if_move_not"
9919 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9920 (if_then_else:SI
9921 (match_operator 4 "arm_comparison_operator"
9922 [(match_operand 3 "cc_register" "") (const_int 0)])
9923 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9924 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9925 "TARGET_ARM"
9926 "@
9927 mvn%D4\\t%0, %2
9928 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9929 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9930 [(set_attr "conds" "use")
9931 (set_attr "type" "mvn_reg")
9932 (set_attr "length" "4,8,8")
9933 (set_attr "type" "mvn_reg,multiple,multiple")]
9934 )
9935
9936 (define_insn "*ifcompare_not_move"
9937 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9938 (if_then_else:SI
9939 (match_operator 5 "arm_comparison_operator"
9940 [(match_operand:SI 3 "s_register_operand" "r,r")
9941 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9942 (not:SI
9943 (match_operand:SI 2 "s_register_operand" "r,r"))
9944 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9945 (clobber (reg:CC CC_REGNUM))]
9946 "TARGET_ARM"
9947 "#"
9948 [(set_attr "conds" "clob")
9949 (set_attr "length" "8,12")
9950 (set_attr "type" "multiple")]
9951 )
9952
9953 (define_insn "*if_not_move"
9954 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9955 (if_then_else:SI
9956 (match_operator 4 "arm_comparison_operator"
9957 [(match_operand 3 "cc_register" "") (const_int 0)])
9958 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9959 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9960 "TARGET_ARM"
9961 "@
9962 mvn%d4\\t%0, %2
9963 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9964 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9965 [(set_attr "conds" "use")
9966 (set_attr "type" "mvn_reg,multiple,multiple")
9967 (set_attr "length" "4,8,8")]
9968 )
9969
9970 (define_insn "*ifcompare_shift_move"
9971 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9972 (if_then_else:SI
9973 (match_operator 6 "arm_comparison_operator"
9974 [(match_operand:SI 4 "s_register_operand" "r,r")
9975 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9976 (match_operator:SI 7 "shift_operator"
9977 [(match_operand:SI 2 "s_register_operand" "r,r")
9978 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9979 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9980 (clobber (reg:CC CC_REGNUM))]
9981 "TARGET_ARM"
9982 "#"
9983 [(set_attr "conds" "clob")
9984 (set_attr "length" "8,12")
9985 (set_attr "type" "multiple")]
9986 )
9987
9988 (define_insn "*if_shift_move"
9989 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9990 (if_then_else:SI
9991 (match_operator 5 "arm_comparison_operator"
9992 [(match_operand 6 "cc_register" "") (const_int 0)])
9993 (match_operator:SI 4 "shift_operator"
9994 [(match_operand:SI 2 "s_register_operand" "r,r,r")
9995 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9996 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9997 "TARGET_ARM"
9998 "@
9999 mov%d5\\t%0, %2%S4
10000 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10001 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10002 [(set_attr "conds" "use")
10003 (set_attr "shift" "2")
10004 (set_attr "length" "4,8,8")
10005 (set_attr_alternative "type"
10006 [(if_then_else (match_operand 3 "const_int_operand" "")
10007 (const_string "mov_shift" )
10008 (const_string "mov_shift_reg"))
10009 (const_string "multiple")
10010 (const_string "multiple")])]
10011 )
10012
10013 (define_insn "*ifcompare_move_shift"
10014 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10015 (if_then_else:SI
10016 (match_operator 6 "arm_comparison_operator"
10017 [(match_operand:SI 4 "s_register_operand" "r,r")
10018 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10019 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10020 (match_operator:SI 7 "shift_operator"
10021 [(match_operand:SI 2 "s_register_operand" "r,r")
10022 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10023 (clobber (reg:CC CC_REGNUM))]
10024 "TARGET_ARM"
10025 "#"
10026 [(set_attr "conds" "clob")
10027 (set_attr "length" "8,12")
10028 (set_attr "type" "multiple")]
10029 )
10030
10031 (define_insn "*if_move_shift"
10032 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10033 (if_then_else:SI
10034 (match_operator 5 "arm_comparison_operator"
10035 [(match_operand 6 "cc_register" "") (const_int 0)])
10036 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10037 (match_operator:SI 4 "shift_operator"
10038 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10039 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10040 "TARGET_ARM"
10041 "@
10042 mov%D5\\t%0, %2%S4
10043 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10044 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10045 [(set_attr "conds" "use")
10046 (set_attr "shift" "2")
10047 (set_attr "length" "4,8,8")
10048 (set_attr_alternative "type"
10049 [(if_then_else (match_operand 3 "const_int_operand" "")
10050 (const_string "mov_shift" )
10051 (const_string "mov_shift_reg"))
10052 (const_string "multiple")
10053 (const_string "multiple")])]
10054 )
10055
10056 (define_insn "*ifcompare_shift_shift"
10057 [(set (match_operand:SI 0 "s_register_operand" "=r")
10058 (if_then_else:SI
10059 (match_operator 7 "arm_comparison_operator"
10060 [(match_operand:SI 5 "s_register_operand" "r")
10061 (match_operand:SI 6 "arm_add_operand" "rIL")])
10062 (match_operator:SI 8 "shift_operator"
10063 [(match_operand:SI 1 "s_register_operand" "r")
10064 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10065 (match_operator:SI 9 "shift_operator"
10066 [(match_operand:SI 3 "s_register_operand" "r")
10067 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10068 (clobber (reg:CC CC_REGNUM))]
10069 "TARGET_ARM"
10070 "#"
10071 [(set_attr "conds" "clob")
10072 (set_attr "length" "12")
10073 (set_attr "type" "multiple")]
10074 )
10075
10076 (define_insn "*if_shift_shift"
10077 [(set (match_operand:SI 0 "s_register_operand" "=r")
10078 (if_then_else:SI
10079 (match_operator 5 "arm_comparison_operator"
10080 [(match_operand 8 "cc_register" "") (const_int 0)])
10081 (match_operator:SI 6 "shift_operator"
10082 [(match_operand:SI 1 "s_register_operand" "r")
10083 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10084 (match_operator:SI 7 "shift_operator"
10085 [(match_operand:SI 3 "s_register_operand" "r")
10086 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10087 "TARGET_ARM"
10088 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10089 [(set_attr "conds" "use")
10090 (set_attr "shift" "1")
10091 (set_attr "length" "8")
10092 (set (attr "type") (if_then_else
10093 (and (match_operand 2 "const_int_operand" "")
10094 (match_operand 4 "const_int_operand" ""))
10095 (const_string "mov_shift")
10096 (const_string "mov_shift_reg")))]
10097 )
10098
10099 (define_insn "*ifcompare_not_arith"
10100 [(set (match_operand:SI 0 "s_register_operand" "=r")
10101 (if_then_else:SI
10102 (match_operator 6 "arm_comparison_operator"
10103 [(match_operand:SI 4 "s_register_operand" "r")
10104 (match_operand:SI 5 "arm_add_operand" "rIL")])
10105 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10106 (match_operator:SI 7 "shiftable_operator"
10107 [(match_operand:SI 2 "s_register_operand" "r")
10108 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
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_not_arith"
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 4 "cc_register" "") (const_int 0)])
10122 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10123 (match_operator:SI 6 "shiftable_operator"
10124 [(match_operand:SI 2 "s_register_operand" "r")
10125 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10126 "TARGET_ARM"
10127 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10128 [(set_attr "conds" "use")
10129 (set_attr "type" "mvn_reg")
10130 (set_attr "length" "8")]
10131 )
10132
10133 (define_insn "*ifcompare_arith_not"
10134 [(set (match_operand:SI 0 "s_register_operand" "=r")
10135 (if_then_else:SI
10136 (match_operator 6 "arm_comparison_operator"
10137 [(match_operand:SI 4 "s_register_operand" "r")
10138 (match_operand:SI 5 "arm_add_operand" "rIL")])
10139 (match_operator:SI 7 "shiftable_operator"
10140 [(match_operand:SI 2 "s_register_operand" "r")
10141 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10142 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10143 (clobber (reg:CC CC_REGNUM))]
10144 "TARGET_ARM"
10145 "#"
10146 [(set_attr "conds" "clob")
10147 (set_attr "length" "12")
10148 (set_attr "type" "multiple")]
10149 )
10150
10151 (define_insn "*if_arith_not"
10152 [(set (match_operand:SI 0 "s_register_operand" "=r")
10153 (if_then_else:SI
10154 (match_operator 5 "arm_comparison_operator"
10155 [(match_operand 4 "cc_register" "") (const_int 0)])
10156 (match_operator:SI 6 "shiftable_operator"
10157 [(match_operand:SI 2 "s_register_operand" "r")
10158 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10159 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10160 "TARGET_ARM"
10161 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10162 [(set_attr "conds" "use")
10163 (set_attr "type" "multiple")
10164 (set_attr "length" "8")]
10165 )
10166
10167 (define_insn "*ifcompare_neg_move"
10168 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10169 (if_then_else:SI
10170 (match_operator 5 "arm_comparison_operator"
10171 [(match_operand:SI 3 "s_register_operand" "r,r")
10172 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10173 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10174 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10175 (clobber (reg:CC CC_REGNUM))]
10176 "TARGET_ARM"
10177 "#"
10178 [(set_attr "conds" "clob")
10179 (set_attr "length" "8,12")
10180 (set_attr "type" "multiple")]
10181 )
10182
10183 (define_insn_and_split "*if_neg_move"
10184 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10185 (if_then_else:SI
10186 (match_operator 4 "arm_comparison_operator"
10187 [(match_operand 3 "cc_register" "") (const_int 0)])
10188 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10189 (match_operand:SI 1 "s_register_operand" "0,0")))]
10190 "TARGET_32BIT"
10191 "#"
10192 "&& reload_completed"
10193 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10194 (set (match_dup 0) (neg:SI (match_dup 2))))]
10195 ""
10196 [(set_attr "conds" "use")
10197 (set_attr "length" "4")
10198 (set_attr "arch" "t2,32")
10199 (set_attr "enabled_for_short_it" "yes,no")
10200 (set_attr "type" "logic_shift_imm")]
10201 )
10202
10203 (define_insn "*ifcompare_move_neg"
10204 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10205 (if_then_else:SI
10206 (match_operator 5 "arm_comparison_operator"
10207 [(match_operand:SI 3 "s_register_operand" "r,r")
10208 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10209 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10210 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10211 (clobber (reg:CC CC_REGNUM))]
10212 "TARGET_ARM"
10213 "#"
10214 [(set_attr "conds" "clob")
10215 (set_attr "length" "8,12")
10216 (set_attr "type" "multiple")]
10217 )
10218
10219 (define_insn_and_split "*if_move_neg"
10220 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10221 (if_then_else:SI
10222 (match_operator 4 "arm_comparison_operator"
10223 [(match_operand 3 "cc_register" "") (const_int 0)])
10224 (match_operand:SI 1 "s_register_operand" "0,0")
10225 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10226 "TARGET_32BIT"
10227 "#"
10228 "&& reload_completed"
10229 [(cond_exec (match_dup 5)
10230 (set (match_dup 0) (neg:SI (match_dup 2))))]
10231 {
10232 machine_mode mode = GET_MODE (operands[3]);
10233 rtx_code rc = GET_CODE (operands[4]);
10234
10235 if (mode == CCFPmode || mode == CCFPEmode)
10236 rc = reverse_condition_maybe_unordered (rc);
10237 else
10238 rc = reverse_condition (rc);
10239
10240 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10241 }
10242 [(set_attr "conds" "use")
10243 (set_attr "length" "4")
10244 (set_attr "arch" "t2,32")
10245 (set_attr "enabled_for_short_it" "yes,no")
10246 (set_attr "type" "logic_shift_imm")]
10247 )
10248
10249 (define_insn "*arith_adjacentmem"
10250 [(set (match_operand:SI 0 "s_register_operand" "=r")
10251 (match_operator:SI 1 "shiftable_operator"
10252 [(match_operand:SI 2 "memory_operand" "m")
10253 (match_operand:SI 3 "memory_operand" "m")]))
10254 (clobber (match_scratch:SI 4 "=r"))]
10255 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10256 "*
10257 {
10258 rtx ldm[3];
10259 rtx arith[4];
10260 rtx base_reg;
10261 HOST_WIDE_INT val1 = 0, val2 = 0;
10262
10263 if (REGNO (operands[0]) > REGNO (operands[4]))
10264 {
10265 ldm[1] = operands[4];
10266 ldm[2] = operands[0];
10267 }
10268 else
10269 {
10270 ldm[1] = operands[0];
10271 ldm[2] = operands[4];
10272 }
10273
10274 base_reg = XEXP (operands[2], 0);
10275
10276 if (!REG_P (base_reg))
10277 {
10278 val1 = INTVAL (XEXP (base_reg, 1));
10279 base_reg = XEXP (base_reg, 0);
10280 }
10281
10282 if (!REG_P (XEXP (operands[3], 0)))
10283 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10284
10285 arith[0] = operands[0];
10286 arith[3] = operands[1];
10287
10288 if (val1 < val2)
10289 {
10290 arith[1] = ldm[1];
10291 arith[2] = ldm[2];
10292 }
10293 else
10294 {
10295 arith[1] = ldm[2];
10296 arith[2] = ldm[1];
10297 }
10298
10299 ldm[0] = base_reg;
10300 if (val1 !=0 && val2 != 0)
10301 {
10302 rtx ops[3];
10303
10304 if (val1 == 4 || val2 == 4)
10305 /* Other val must be 8, since we know they are adjacent and neither
10306 is zero. */
10307 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
10308 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10309 {
10310 ldm[0] = ops[0] = operands[4];
10311 ops[1] = base_reg;
10312 ops[2] = GEN_INT (val1);
10313 output_add_immediate (ops);
10314 if (val1 < val2)
10315 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10316 else
10317 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10318 }
10319 else
10320 {
10321 /* Offset is out of range for a single add, so use two ldr. */
10322 ops[0] = ldm[1];
10323 ops[1] = base_reg;
10324 ops[2] = GEN_INT (val1);
10325 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10326 ops[0] = ldm[2];
10327 ops[2] = GEN_INT (val2);
10328 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10329 }
10330 }
10331 else if (val1 != 0)
10332 {
10333 if (val1 < val2)
10334 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10335 else
10336 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10337 }
10338 else
10339 {
10340 if (val1 < val2)
10341 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10342 else
10343 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10344 }
10345 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10346 return \"\";
10347 }"
10348 [(set_attr "length" "12")
10349 (set_attr "predicable" "yes")
10350 (set_attr "type" "load_4")]
10351 )
10352
10353 ; This pattern is never tried by combine, so do it as a peephole
10354
10355 (define_peephole2
10356 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10357 (match_operand:SI 1 "arm_general_register_operand" ""))
10358 (set (reg:CC CC_REGNUM)
10359 (compare:CC (match_dup 1) (const_int 0)))]
10360 "TARGET_ARM"
10361 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10362 (set (match_dup 0) (match_dup 1))])]
10363 ""
10364 )
10365
10366 (define_split
10367 [(set (match_operand:SI 0 "s_register_operand" "")
10368 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10369 (const_int 0))
10370 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10371 [(match_operand:SI 3 "s_register_operand" "")
10372 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10373 (clobber (match_operand:SI 5 "s_register_operand" ""))]
10374 "TARGET_ARM"
10375 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10376 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10377 (match_dup 5)))]
10378 ""
10379 )
10380
10381 ;; This split can be used because CC_Z mode implies that the following
10382 ;; branch will be an equality, or an unsigned inequality, so the sign
10383 ;; extension is not needed.
10384
10385 (define_split
10386 [(set (reg:CC_Z CC_REGNUM)
10387 (compare:CC_Z
10388 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10389 (const_int 24))
10390 (match_operand 1 "const_int_operand" "")))
10391 (clobber (match_scratch:SI 2 ""))]
10392 "TARGET_ARM
10393 && ((UINTVAL (operands[1]))
10394 == ((UINTVAL (operands[1])) >> 24) << 24)"
10395 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10396 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10397 "
10398 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10399 "
10400 )
10401 ;; ??? Check the patterns above for Thumb-2 usefulness
10402
10403 (define_expand "prologue"
10404 [(clobber (const_int 0))]
10405 "TARGET_EITHER"
10406 "if (TARGET_32BIT)
10407 arm_expand_prologue ();
10408 else
10409 thumb1_expand_prologue ();
10410 DONE;
10411 "
10412 )
10413
10414 (define_expand "epilogue"
10415 [(clobber (const_int 0))]
10416 "TARGET_EITHER"
10417 "
10418 if (crtl->calls_eh_return)
10419 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
10420 if (TARGET_THUMB1)
10421 {
10422 thumb1_expand_epilogue ();
10423 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10424 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10425 }
10426 else if (HAVE_return)
10427 {
10428 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10429 no need for explicit testing again. */
10430 emit_jump_insn (gen_return ());
10431 }
10432 else if (TARGET_32BIT)
10433 {
10434 arm_expand_epilogue (true);
10435 }
10436 DONE;
10437 "
10438 )
10439
10440 ;; Note - although unspec_volatile's USE all hard registers,
10441 ;; USEs are ignored after relaod has completed. Thus we need
10442 ;; to add an unspec of the link register to ensure that flow
10443 ;; does not think that it is unused by the sibcall branch that
10444 ;; will replace the standard function epilogue.
10445 (define_expand "sibcall_epilogue"
10446 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
10447 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10448 "TARGET_32BIT"
10449 "
10450 arm_expand_epilogue (false);
10451 DONE;
10452 "
10453 )
10454
10455 (define_expand "eh_epilogue"
10456 [(use (match_operand:SI 0 "register_operand"))
10457 (use (match_operand:SI 1 "register_operand"))
10458 (use (match_operand:SI 2 "register_operand"))]
10459 "TARGET_EITHER"
10460 "
10461 {
10462 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10463 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
10464 {
10465 rtx ra = gen_rtx_REG (Pmode, 2);
10466
10467 emit_move_insn (ra, operands[2]);
10468 operands[2] = ra;
10469 }
10470 /* This is a hack -- we may have crystalized the function type too
10471 early. */
10472 cfun->machine->func_type = 0;
10473 }"
10474 )
10475
10476 ;; This split is only used during output to reduce the number of patterns
10477 ;; that need assembler instructions adding to them. We allowed the setting
10478 ;; of the conditions to be implicit during rtl generation so that
10479 ;; the conditional compare patterns would work. However this conflicts to
10480 ;; some extent with the conditional data operations, so we have to split them
10481 ;; up again here.
10482
10483 ;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10484 ;; conditional execution sufficient?
10485
10486 (define_split
10487 [(set (match_operand:SI 0 "s_register_operand" "")
10488 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10489 [(match_operand 2 "" "") (match_operand 3 "" "")])
10490 (match_dup 0)
10491 (match_operand 4 "" "")))
10492 (clobber (reg:CC CC_REGNUM))]
10493 "TARGET_ARM && reload_completed"
10494 [(set (match_dup 5) (match_dup 6))
10495 (cond_exec (match_dup 7)
10496 (set (match_dup 0) (match_dup 4)))]
10497 "
10498 {
10499 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10500 operands[2], operands[3]);
10501 enum rtx_code rc = GET_CODE (operands[1]);
10502
10503 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10504 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10505 if (mode == CCFPmode || mode == CCFPEmode)
10506 rc = reverse_condition_maybe_unordered (rc);
10507 else
10508 rc = reverse_condition (rc);
10509
10510 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10511 }"
10512 )
10513
10514 (define_split
10515 [(set (match_operand:SI 0 "s_register_operand" "")
10516 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10517 [(match_operand 2 "" "") (match_operand 3 "" "")])
10518 (match_operand 4 "" "")
10519 (match_dup 0)))
10520 (clobber (reg:CC CC_REGNUM))]
10521 "TARGET_ARM && reload_completed"
10522 [(set (match_dup 5) (match_dup 6))
10523 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10524 (set (match_dup 0) (match_dup 4)))]
10525 "
10526 {
10527 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10528 operands[2], operands[3]);
10529
10530 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10531 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10532 }"
10533 )
10534
10535 (define_split
10536 [(set (match_operand:SI 0 "s_register_operand" "")
10537 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10538 [(match_operand 2 "" "") (match_operand 3 "" "")])
10539 (match_operand 4 "" "")
10540 (match_operand 5 "" "")))
10541 (clobber (reg:CC CC_REGNUM))]
10542 "TARGET_ARM && reload_completed"
10543 [(set (match_dup 6) (match_dup 7))
10544 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10545 (set (match_dup 0) (match_dup 4)))
10546 (cond_exec (match_dup 8)
10547 (set (match_dup 0) (match_dup 5)))]
10548 "
10549 {
10550 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10551 operands[2], operands[3]);
10552 enum rtx_code rc = GET_CODE (operands[1]);
10553
10554 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10555 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10556 if (mode == CCFPmode || mode == CCFPEmode)
10557 rc = reverse_condition_maybe_unordered (rc);
10558 else
10559 rc = reverse_condition (rc);
10560
10561 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10562 }"
10563 )
10564
10565 (define_split
10566 [(set (match_operand:SI 0 "s_register_operand" "")
10567 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10568 [(match_operand:SI 2 "s_register_operand" "")
10569 (match_operand:SI 3 "arm_add_operand" "")])
10570 (match_operand:SI 4 "arm_rhs_operand" "")
10571 (not:SI
10572 (match_operand:SI 5 "s_register_operand" ""))))
10573 (clobber (reg:CC CC_REGNUM))]
10574 "TARGET_ARM && reload_completed"
10575 [(set (match_dup 6) (match_dup 7))
10576 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10577 (set (match_dup 0) (match_dup 4)))
10578 (cond_exec (match_dup 8)
10579 (set (match_dup 0) (not:SI (match_dup 5))))]
10580 "
10581 {
10582 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10583 operands[2], operands[3]);
10584 enum rtx_code rc = GET_CODE (operands[1]);
10585
10586 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10587 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10588 if (mode == CCFPmode || mode == CCFPEmode)
10589 rc = reverse_condition_maybe_unordered (rc);
10590 else
10591 rc = reverse_condition (rc);
10592
10593 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10594 }"
10595 )
10596
10597 (define_insn "*cond_move_not"
10598 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10599 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10600 [(match_operand 3 "cc_register" "") (const_int 0)])
10601 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10602 (not:SI
10603 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10604 "TARGET_ARM"
10605 "@
10606 mvn%D4\\t%0, %2
10607 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10608 [(set_attr "conds" "use")
10609 (set_attr "type" "mvn_reg,multiple")
10610 (set_attr "length" "4,8")]
10611 )
10612
10613 ;; The next two patterns occur when an AND operation is followed by a
10614 ;; scc insn sequence
10615
10616 (define_insn "*sign_extract_onebit"
10617 [(set (match_operand:SI 0 "s_register_operand" "=r")
10618 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10619 (const_int 1)
10620 (match_operand:SI 2 "const_int_operand" "n")))
10621 (clobber (reg:CC CC_REGNUM))]
10622 "TARGET_ARM"
10623 "*
10624 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10625 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10626 return \"mvnne\\t%0, #0\";
10627 "
10628 [(set_attr "conds" "clob")
10629 (set_attr "length" "8")
10630 (set_attr "type" "multiple")]
10631 )
10632
10633 (define_insn "*not_signextract_onebit"
10634 [(set (match_operand:SI 0 "s_register_operand" "=r")
10635 (not:SI
10636 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10637 (const_int 1)
10638 (match_operand:SI 2 "const_int_operand" "n"))))
10639 (clobber (reg:CC CC_REGNUM))]
10640 "TARGET_ARM"
10641 "*
10642 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10643 output_asm_insn (\"tst\\t%1, %2\", operands);
10644 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10645 return \"movne\\t%0, #0\";
10646 "
10647 [(set_attr "conds" "clob")
10648 (set_attr "length" "12")
10649 (set_attr "type" "multiple")]
10650 )
10651 ;; ??? The above patterns need auditing for Thumb-2
10652
10653 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10654 ;; expressions. For simplicity, the first register is also in the unspec
10655 ;; part.
10656 ;; To avoid the usage of GNU extension, the length attribute is computed
10657 ;; in a C function arm_attr_length_push_multi.
10658 (define_insn "*push_multi"
10659 [(match_parallel 2 "multi_register_push"
10660 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10661 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10662 UNSPEC_PUSH_MULT))])]
10663 ""
10664 "*
10665 {
10666 int num_saves = XVECLEN (operands[2], 0);
10667
10668 /* For the StrongARM at least it is faster to
10669 use STR to store only a single register.
10670 In Thumb mode always use push, and the assembler will pick
10671 something appropriate. */
10672 if (num_saves == 1 && TARGET_ARM)
10673 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
10674 else
10675 {
10676 int i;
10677 char pattern[100];
10678
10679 if (TARGET_32BIT)
10680 strcpy (pattern, \"push%?\\t{%1\");
10681 else
10682 strcpy (pattern, \"push\\t{%1\");
10683
10684 for (i = 1; i < num_saves; i++)
10685 {
10686 strcat (pattern, \", %|\");
10687 strcat (pattern,
10688 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10689 }
10690
10691 strcat (pattern, \"}\");
10692 output_asm_insn (pattern, operands);
10693 }
10694
10695 return \"\";
10696 }"
10697 [(set_attr "type" "store_16")
10698 (set (attr "length")
10699 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
10700 )
10701
10702 (define_insn "stack_tie"
10703 [(set (mem:BLK (scratch))
10704 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10705 (match_operand:SI 1 "s_register_operand" "rk")]
10706 UNSPEC_PRLG_STK))]
10707 ""
10708 ""
10709 [(set_attr "length" "0")
10710 (set_attr "type" "block")]
10711 )
10712
10713 ;; Pop (as used in epilogue RTL)
10714 ;;
10715 (define_insn "*load_multiple_with_writeback"
10716 [(match_parallel 0 "load_multiple_operation"
10717 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10718 (plus:SI (match_dup 1)
10719 (match_operand:SI 2 "const_int_I_operand" "I")))
10720 (set (match_operand:SI 3 "s_register_operand" "=rk")
10721 (mem:SI (match_dup 1)))
10722 ])]
10723 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10724 "*
10725 {
10726 arm_output_multireg_pop (operands, /*return_pc=*/false,
10727 /*cond=*/const_true_rtx,
10728 /*reverse=*/false,
10729 /*update=*/true);
10730 return \"\";
10731 }
10732 "
10733 [(set_attr "type" "load_16")
10734 (set_attr "predicable" "yes")
10735 (set (attr "length")
10736 (symbol_ref "arm_attr_length_pop_multi (operands,
10737 /*return_pc=*/false,
10738 /*write_back_p=*/true)"))]
10739 )
10740
10741 ;; Pop with return (as used in epilogue RTL)
10742 ;;
10743 ;; This instruction is generated when the registers are popped at the end of
10744 ;; epilogue. Here, instead of popping the value into LR and then generating
10745 ;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10746 ;; with (return).
10747 (define_insn "*pop_multiple_with_writeback_and_return"
10748 [(match_parallel 0 "pop_multiple_return"
10749 [(return)
10750 (set (match_operand:SI 1 "s_register_operand" "+rk")
10751 (plus:SI (match_dup 1)
10752 (match_operand:SI 2 "const_int_I_operand" "I")))
10753 (set (match_operand:SI 3 "s_register_operand" "=rk")
10754 (mem:SI (match_dup 1)))
10755 ])]
10756 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10757 "*
10758 {
10759 arm_output_multireg_pop (operands, /*return_pc=*/true,
10760 /*cond=*/const_true_rtx,
10761 /*reverse=*/false,
10762 /*update=*/true);
10763 return \"\";
10764 }
10765 "
10766 [(set_attr "type" "load_16")
10767 (set_attr "predicable" "yes")
10768 (set (attr "length")
10769 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10770 /*write_back_p=*/true)"))]
10771 )
10772
10773 (define_insn "*pop_multiple_with_return"
10774 [(match_parallel 0 "pop_multiple_return"
10775 [(return)
10776 (set (match_operand:SI 2 "s_register_operand" "=rk")
10777 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10778 ])]
10779 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10780 "*
10781 {
10782 arm_output_multireg_pop (operands, /*return_pc=*/true,
10783 /*cond=*/const_true_rtx,
10784 /*reverse=*/false,
10785 /*update=*/false);
10786 return \"\";
10787 }
10788 "
10789 [(set_attr "type" "load_16")
10790 (set_attr "predicable" "yes")
10791 (set (attr "length")
10792 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10793 /*write_back_p=*/false)"))]
10794 )
10795
10796 ;; Load into PC and return
10797 (define_insn "*ldr_with_return"
10798 [(return)
10799 (set (reg:SI PC_REGNUM)
10800 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10801 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10802 "ldr%?\t%|pc, [%0], #4"
10803 [(set_attr "type" "load_4")
10804 (set_attr "predicable" "yes")]
10805 )
10806 ;; Pop for floating point registers (as used in epilogue RTL)
10807 (define_insn "*vfp_pop_multiple_with_writeback"
10808 [(match_parallel 0 "pop_multiple_fp"
10809 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10810 (plus:SI (match_dup 1)
10811 (match_operand:SI 2 "const_int_I_operand" "I")))
10812 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
10813 (mem:DF (match_dup 1)))])]
10814 "TARGET_32BIT && TARGET_HARD_FLOAT"
10815 "*
10816 {
10817 int num_regs = XVECLEN (operands[0], 0);
10818 char pattern[100];
10819 rtx op_list[2];
10820 strcpy (pattern, \"vldm\\t\");
10821 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10822 strcat (pattern, \"!, {\");
10823 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10824 strcat (pattern, \"%P0\");
10825 if ((num_regs - 1) > 1)
10826 {
10827 strcat (pattern, \"-%P1\");
10828 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10829 }
10830
10831 strcat (pattern, \"}\");
10832 output_asm_insn (pattern, op_list);
10833 return \"\";
10834 }
10835 "
10836 [(set_attr "type" "load_16")
10837 (set_attr "conds" "unconditional")
10838 (set_attr "predicable" "no")]
10839 )
10840
10841 ;; Special patterns for dealing with the constant pool
10842
10843 (define_insn "align_4"
10844 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10845 "TARGET_EITHER"
10846 "*
10847 assemble_align (32);
10848 return \"\";
10849 "
10850 [(set_attr "type" "no_insn")]
10851 )
10852
10853 (define_insn "align_8"
10854 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10855 "TARGET_EITHER"
10856 "*
10857 assemble_align (64);
10858 return \"\";
10859 "
10860 [(set_attr "type" "no_insn")]
10861 )
10862
10863 (define_insn "consttable_end"
10864 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10865 "TARGET_EITHER"
10866 "*
10867 making_const_table = FALSE;
10868 return \"\";
10869 "
10870 [(set_attr "type" "no_insn")]
10871 )
10872
10873 (define_insn "consttable_1"
10874 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10875 "TARGET_EITHER"
10876 "*
10877 making_const_table = TRUE;
10878 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10879 assemble_zeros (3);
10880 return \"\";
10881 "
10882 [(set_attr "length" "4")
10883 (set_attr "type" "no_insn")]
10884 )
10885
10886 (define_insn "consttable_2"
10887 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10888 "TARGET_EITHER"
10889 "*
10890 {
10891 rtx x = operands[0];
10892 making_const_table = TRUE;
10893 switch (GET_MODE_CLASS (GET_MODE (x)))
10894 {
10895 case MODE_FLOAT:
10896 arm_emit_fp16_const (x);
10897 break;
10898 default:
10899 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10900 assemble_zeros (2);
10901 break;
10902 }
10903 return \"\";
10904 }"
10905 [(set_attr "length" "4")
10906 (set_attr "type" "no_insn")]
10907 )
10908
10909 (define_insn "consttable_4"
10910 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10911 "TARGET_EITHER"
10912 "*
10913 {
10914 rtx x = operands[0];
10915 making_const_table = TRUE;
10916 scalar_float_mode float_mode;
10917 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
10918 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
10919 else
10920 {
10921 /* XXX: Sometimes gcc does something really dumb and ends up with
10922 a HIGH in a constant pool entry, usually because it's trying to
10923 load into a VFP register. We know this will always be used in
10924 combination with a LO_SUM which ignores the high bits, so just
10925 strip off the HIGH. */
10926 if (GET_CODE (x) == HIGH)
10927 x = XEXP (x, 0);
10928 assemble_integer (x, 4, BITS_PER_WORD, 1);
10929 mark_symbol_refs_as_used (x);
10930 }
10931 return \"\";
10932 }"
10933 [(set_attr "length" "4")
10934 (set_attr "type" "no_insn")]
10935 )
10936
10937 (define_insn "consttable_8"
10938 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10939 "TARGET_EITHER"
10940 "*
10941 {
10942 making_const_table = TRUE;
10943 scalar_float_mode float_mode;
10944 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10945 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10946 float_mode, BITS_PER_WORD);
10947 else
10948 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10949 return \"\";
10950 }"
10951 [(set_attr "length" "8")
10952 (set_attr "type" "no_insn")]
10953 )
10954
10955 (define_insn "consttable_16"
10956 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10957 "TARGET_EITHER"
10958 "*
10959 {
10960 making_const_table = TRUE;
10961 scalar_float_mode float_mode;
10962 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
10963 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
10964 float_mode, BITS_PER_WORD);
10965 else
10966 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10967 return \"\";
10968 }"
10969 [(set_attr "length" "16")
10970 (set_attr "type" "no_insn")]
10971 )
10972
10973 ;; V5 Instructions,
10974
10975 (define_insn "clzsi2"
10976 [(set (match_operand:SI 0 "s_register_operand" "=r")
10977 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10978 "TARGET_32BIT && arm_arch5t"
10979 "clz%?\\t%0, %1"
10980 [(set_attr "predicable" "yes")
10981 (set_attr "type" "clz")])
10982
10983 (define_insn "rbitsi2"
10984 [(set (match_operand:SI 0 "s_register_operand" "=r")
10985 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10986 "TARGET_32BIT && arm_arch_thumb2"
10987 "rbit%?\\t%0, %1"
10988 [(set_attr "predicable" "yes")
10989 (set_attr "type" "clz")])
10990
10991 ;; Keep this as a CTZ expression until after reload and then split
10992 ;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
10993 ;; to fold with any other expression.
10994
10995 (define_insn_and_split "ctzsi2"
10996 [(set (match_operand:SI 0 "s_register_operand" "=r")
10997 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10998 "TARGET_32BIT && arm_arch_thumb2"
10999 "#"
11000 "&& reload_completed"
11001 [(const_int 0)]
11002 "
11003 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11004 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11005 DONE;
11006 ")
11007
11008 ;; V5E instructions.
11009
11010 (define_insn "prefetch"
11011 [(prefetch (match_operand:SI 0 "address_operand" "p")
11012 (match_operand:SI 1 "" "")
11013 (match_operand:SI 2 "" ""))]
11014 "TARGET_32BIT && arm_arch5te"
11015 "pld\\t%a0"
11016 [(set_attr "type" "load_4")]
11017 )
11018
11019 ;; General predication pattern
11020
11021 (define_cond_exec
11022 [(match_operator 0 "arm_comparison_operator"
11023 [(match_operand 1 "cc_register" "")
11024 (const_int 0)])]
11025 "TARGET_32BIT
11026 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
11027 ""
11028 [(set_attr "predicated" "yes")]
11029 )
11030
11031 (define_insn "force_register_use"
11032 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
11033 ""
11034 "%@ %0 needed"
11035 [(set_attr "length" "0")
11036 (set_attr "type" "no_insn")]
11037 )
11038
11039
11040 ;; Patterns for exception handling
11041
11042 (define_expand "eh_return"
11043 [(use (match_operand 0 "general_operand"))]
11044 "TARGET_EITHER"
11045 "
11046 {
11047 if (TARGET_32BIT)
11048 emit_insn (gen_arm_eh_return (operands[0]));
11049 else
11050 emit_insn (gen_thumb_eh_return (operands[0]));
11051 DONE;
11052 }"
11053 )
11054
11055 ;; We can't expand this before we know where the link register is stored.
11056 (define_insn_and_split "arm_eh_return"
11057 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11058 VUNSPEC_EH_RETURN)
11059 (clobber (match_scratch:SI 1 "=&r"))]
11060 "TARGET_ARM"
11061 "#"
11062 "&& reload_completed"
11063 [(const_int 0)]
11064 "
11065 {
11066 arm_set_return_address (operands[0], operands[1]);
11067 DONE;
11068 }"
11069 )
11070
11071 \f
11072 ;; TLS support
11073
11074 (define_insn "load_tp_hard"
11075 [(set (match_operand:SI 0 "register_operand" "=r")
11076 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11077 "TARGET_HARD_TP"
11078 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11079 [(set_attr "predicable" "yes")
11080 (set_attr "type" "mrs")]
11081 )
11082
11083 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11084 (define_insn "load_tp_soft_fdpic"
11085 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11086 (clobber (reg:SI FDPIC_REGNUM))
11087 (clobber (reg:SI LR_REGNUM))
11088 (clobber (reg:SI IP_REGNUM))
11089 (clobber (reg:CC CC_REGNUM))]
11090 "TARGET_SOFT_TP && TARGET_FDPIC"
11091 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11092 [(set_attr "conds" "clob")
11093 (set_attr "type" "branch")]
11094 )
11095
11096 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11097 (define_insn "load_tp_soft"
11098 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11099 (clobber (reg:SI LR_REGNUM))
11100 (clobber (reg:SI IP_REGNUM))
11101 (clobber (reg:CC CC_REGNUM))]
11102 "TARGET_SOFT_TP && !TARGET_FDPIC"
11103 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11104 [(set_attr "conds" "clob")
11105 (set_attr "type" "branch")]
11106 )
11107
11108 ;; tls descriptor call
11109 (define_insn "tlscall"
11110 [(set (reg:SI R0_REGNUM)
11111 (unspec:SI [(reg:SI R0_REGNUM)
11112 (match_operand:SI 0 "" "X")
11113 (match_operand 1 "" "")] UNSPEC_TLS))
11114 (clobber (reg:SI R1_REGNUM))
11115 (clobber (reg:SI LR_REGNUM))
11116 (clobber (reg:SI CC_REGNUM))]
11117 "TARGET_GNU2_TLS"
11118 {
11119 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11120 INTVAL (operands[1]));
11121 return "bl\\t%c0(tlscall)";
11122 }
11123 [(set_attr "conds" "clob")
11124 (set_attr "length" "4")
11125 (set_attr "type" "branch")]
11126 )
11127
11128 ;; For thread pointer builtin
11129 (define_expand "get_thread_pointersi"
11130 [(match_operand:SI 0 "s_register_operand")]
11131 ""
11132 "
11133 {
11134 arm_load_tp (operands[0]);
11135 DONE;
11136 }")
11137
11138 ;;
11139
11140 ;; We only care about the lower 16 bits of the constant
11141 ;; being inserted into the upper 16 bits of the register.
11142 (define_insn "*arm_movtas_ze"
11143 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
11144 (const_int 16)
11145 (const_int 16))
11146 (match_operand:SI 1 "const_int_operand" ""))]
11147 "TARGET_HAVE_MOVT"
11148 "@
11149 movt%?\t%0, %L1
11150 movt\t%0, %L1"
11151 [(set_attr "arch" "32,v8mb")
11152 (set_attr "predicable" "yes")
11153 (set_attr "length" "4")
11154 (set_attr "type" "alu_sreg")]
11155 )
11156
11157 (define_insn "*arm_rev"
11158 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11159 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11160 "arm_arch6"
11161 "@
11162 rev\t%0, %1
11163 rev%?\t%0, %1
11164 rev%?\t%0, %1"
11165 [(set_attr "arch" "t1,t2,32")
11166 (set_attr "length" "2,2,4")
11167 (set_attr "predicable" "no,yes,yes")
11168 (set_attr "type" "rev")]
11169 )
11170
11171 (define_expand "arm_legacy_rev"
11172 [(set (match_operand:SI 2 "s_register_operand")
11173 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
11174 (const_int 16))
11175 (match_dup 1)))
11176 (set (match_dup 2)
11177 (lshiftrt:SI (match_dup 2)
11178 (const_int 8)))
11179 (set (match_operand:SI 3 "s_register_operand")
11180 (rotatert:SI (match_dup 1)
11181 (const_int 8)))
11182 (set (match_dup 2)
11183 (and:SI (match_dup 2)
11184 (const_int -65281)))
11185 (set (match_operand:SI 0 "s_register_operand")
11186 (xor:SI (match_dup 3)
11187 (match_dup 2)))]
11188 "TARGET_32BIT"
11189 ""
11190 )
11191
11192 ;; Reuse temporaries to keep register pressure down.
11193 (define_expand "thumb_legacy_rev"
11194 [(set (match_operand:SI 2 "s_register_operand")
11195 (ashift:SI (match_operand:SI 1 "s_register_operand")
11196 (const_int 24)))
11197 (set (match_operand:SI 3 "s_register_operand")
11198 (lshiftrt:SI (match_dup 1)
11199 (const_int 24)))
11200 (set (match_dup 3)
11201 (ior:SI (match_dup 3)
11202 (match_dup 2)))
11203 (set (match_operand:SI 4 "s_register_operand")
11204 (const_int 16))
11205 (set (match_operand:SI 5 "s_register_operand")
11206 (rotatert:SI (match_dup 1)
11207 (match_dup 4)))
11208 (set (match_dup 2)
11209 (ashift:SI (match_dup 5)
11210 (const_int 24)))
11211 (set (match_dup 5)
11212 (lshiftrt:SI (match_dup 5)
11213 (const_int 24)))
11214 (set (match_dup 5)
11215 (ior:SI (match_dup 5)
11216 (match_dup 2)))
11217 (set (match_dup 5)
11218 (rotatert:SI (match_dup 5)
11219 (match_dup 4)))
11220 (set (match_operand:SI 0 "s_register_operand")
11221 (ior:SI (match_dup 5)
11222 (match_dup 3)))]
11223 "TARGET_THUMB"
11224 ""
11225 )
11226
11227 ;; ARM-specific expansion of signed mod by power of 2
11228 ;; using conditional negate.
11229 ;; For r0 % n where n is a power of 2 produce:
11230 ;; rsbs r1, r0, #0
11231 ;; and r0, r0, #(n - 1)
11232 ;; and r1, r1, #(n - 1)
11233 ;; rsbpl r0, r1, #0
11234
11235 (define_expand "modsi3"
11236 [(match_operand:SI 0 "register_operand")
11237 (match_operand:SI 1 "register_operand")
11238 (match_operand:SI 2 "const_int_operand")]
11239 "TARGET_32BIT"
11240 {
11241 HOST_WIDE_INT val = INTVAL (operands[2]);
11242
11243 if (val <= 0
11244 || exact_log2 (val) <= 0)
11245 FAIL;
11246
11247 rtx mask = GEN_INT (val - 1);
11248
11249 /* In the special case of x0 % 2 we can do the even shorter:
11250 cmp r0, #0
11251 and r0, r0, #1
11252 rsblt r0, r0, #0. */
11253
11254 if (val == 2)
11255 {
11256 rtx cc_reg = arm_gen_compare_reg (LT,
11257 operands[1], const0_rtx, NULL_RTX);
11258 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11259 rtx masked = gen_reg_rtx (SImode);
11260
11261 emit_insn (gen_andsi3 (masked, operands[1], mask));
11262 emit_move_insn (operands[0],
11263 gen_rtx_IF_THEN_ELSE (SImode, cond,
11264 gen_rtx_NEG (SImode,
11265 masked),
11266 masked));
11267 DONE;
11268 }
11269
11270 rtx neg_op = gen_reg_rtx (SImode);
11271 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11272 operands[1]));
11273
11274 /* Extract the condition register and mode. */
11275 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11276 rtx cc_reg = SET_DEST (cmp);
11277 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11278
11279 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11280
11281 rtx masked_neg = gen_reg_rtx (SImode);
11282 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11283
11284 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11285 during expand does not always work. Do an IF_THEN_ELSE instead. */
11286 emit_move_insn (operands[0],
11287 gen_rtx_IF_THEN_ELSE (SImode, cond,
11288 gen_rtx_NEG (SImode, masked_neg),
11289 operands[0]));
11290
11291
11292 DONE;
11293 }
11294 )
11295
11296 (define_expand "bswapsi2"
11297 [(set (match_operand:SI 0 "s_register_operand")
11298 (bswap:SI (match_operand:SI 1 "s_register_operand")))]
11299 "TARGET_EITHER && (arm_arch6 || !optimize_size)"
11300 "
11301 if (!arm_arch6)
11302 {
11303 rtx op2 = gen_reg_rtx (SImode);
11304 rtx op3 = gen_reg_rtx (SImode);
11305
11306 if (TARGET_THUMB)
11307 {
11308 rtx op4 = gen_reg_rtx (SImode);
11309 rtx op5 = gen_reg_rtx (SImode);
11310
11311 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11312 op2, op3, op4, op5));
11313 }
11314 else
11315 {
11316 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11317 op2, op3));
11318 }
11319
11320 DONE;
11321 }
11322 "
11323 )
11324
11325 ;; bswap16 patterns: use revsh and rev16 instructions for the signed
11326 ;; and unsigned variants, respectively. For rev16, expose
11327 ;; byte-swapping in the lower 16 bits only.
11328 (define_insn "*arm_revsh"
11329 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11330 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11331 "arm_arch6"
11332 "@
11333 revsh\t%0, %1
11334 revsh%?\t%0, %1
11335 revsh%?\t%0, %1"
11336 [(set_attr "arch" "t1,t2,32")
11337 (set_attr "length" "2,2,4")
11338 (set_attr "type" "rev")]
11339 )
11340
11341 (define_insn "*arm_rev16"
11342 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11343 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11344 "arm_arch6"
11345 "@
11346 rev16\t%0, %1
11347 rev16%?\t%0, %1
11348 rev16%?\t%0, %1"
11349 [(set_attr "arch" "t1,t2,32")
11350 (set_attr "length" "2,2,4")
11351 (set_attr "type" "rev")]
11352 )
11353
11354 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11355 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
11356 ;; each valid permutation.
11357
11358 (define_insn "arm_rev16si2"
11359 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11360 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11361 (const_int 8))
11362 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11363 (and:SI (lshiftrt:SI (match_dup 1)
11364 (const_int 8))
11365 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11366 "arm_arch6
11367 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11368 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11369 "rev16\\t%0, %1"
11370 [(set_attr "arch" "t1,t2,32")
11371 (set_attr "length" "2,2,4")
11372 (set_attr "type" "rev")]
11373 )
11374
11375 (define_insn "arm_rev16si2_alt"
11376 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11377 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11378 (const_int 8))
11379 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11380 (and:SI (ashift:SI (match_dup 1)
11381 (const_int 8))
11382 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11383 "arm_arch6
11384 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11385 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11386 "rev16\\t%0, %1"
11387 [(set_attr "arch" "t1,t2,32")
11388 (set_attr "length" "2,2,4")
11389 (set_attr "type" "rev")]
11390 )
11391
11392 (define_expand "bswaphi2"
11393 [(set (match_operand:HI 0 "s_register_operand")
11394 (bswap:HI (match_operand:HI 1 "s_register_operand")))]
11395 "arm_arch6"
11396 ""
11397 )
11398
11399 ;; Patterns for LDRD/STRD in Thumb2 mode
11400
11401 (define_insn "*thumb2_ldrd"
11402 [(set (match_operand:SI 0 "s_register_operand" "=r")
11403 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11404 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11405 (set (match_operand:SI 3 "s_register_operand" "=r")
11406 (mem:SI (plus:SI (match_dup 1)
11407 (match_operand:SI 4 "const_int_operand" ""))))]
11408 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11409 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11410 && (operands_ok_ldrd_strd (operands[0], operands[3],
11411 operands[1], INTVAL (operands[2]),
11412 false, true))"
11413 "ldrd%?\t%0, %3, [%1, %2]"
11414 [(set_attr "type" "load_8")
11415 (set_attr "predicable" "yes")])
11416
11417 (define_insn "*thumb2_ldrd_base"
11418 [(set (match_operand:SI 0 "s_register_operand" "=r")
11419 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11420 (set (match_operand:SI 2 "s_register_operand" "=r")
11421 (mem:SI (plus:SI (match_dup 1)
11422 (const_int 4))))]
11423 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11424 && (operands_ok_ldrd_strd (operands[0], operands[2],
11425 operands[1], 0, false, true))"
11426 "ldrd%?\t%0, %2, [%1]"
11427 [(set_attr "type" "load_8")
11428 (set_attr "predicable" "yes")])
11429
11430 (define_insn "*thumb2_ldrd_base_neg"
11431 [(set (match_operand:SI 0 "s_register_operand" "=r")
11432 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11433 (const_int -4))))
11434 (set (match_operand:SI 2 "s_register_operand" "=r")
11435 (mem:SI (match_dup 1)))]
11436 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11437 && (operands_ok_ldrd_strd (operands[0], operands[2],
11438 operands[1], -4, false, true))"
11439 "ldrd%?\t%0, %2, [%1, #-4]"
11440 [(set_attr "type" "load_8")
11441 (set_attr "predicable" "yes")])
11442
11443 (define_insn "*thumb2_strd"
11444 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11445 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11446 (match_operand:SI 2 "s_register_operand" "r"))
11447 (set (mem:SI (plus:SI (match_dup 0)
11448 (match_operand:SI 3 "const_int_operand" "")))
11449 (match_operand:SI 4 "s_register_operand" "r"))]
11450 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11451 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11452 && (operands_ok_ldrd_strd (operands[2], operands[4],
11453 operands[0], INTVAL (operands[1]),
11454 false, false))"
11455 "strd%?\t%2, %4, [%0, %1]"
11456 [(set_attr "type" "store_8")
11457 (set_attr "predicable" "yes")])
11458
11459 (define_insn "*thumb2_strd_base"
11460 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11461 (match_operand:SI 1 "s_register_operand" "r"))
11462 (set (mem:SI (plus:SI (match_dup 0)
11463 (const_int 4)))
11464 (match_operand:SI 2 "s_register_operand" "r"))]
11465 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11466 && (operands_ok_ldrd_strd (operands[1], operands[2],
11467 operands[0], 0, false, false))"
11468 "strd%?\t%1, %2, [%0]"
11469 [(set_attr "type" "store_8")
11470 (set_attr "predicable" "yes")])
11471
11472 (define_insn "*thumb2_strd_base_neg"
11473 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11474 (const_int -4)))
11475 (match_operand:SI 1 "s_register_operand" "r"))
11476 (set (mem:SI (match_dup 0))
11477 (match_operand:SI 2 "s_register_operand" "r"))]
11478 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11479 && (operands_ok_ldrd_strd (operands[1], operands[2],
11480 operands[0], -4, false, false))"
11481 "strd%?\t%1, %2, [%0, #-4]"
11482 [(set_attr "type" "store_8")
11483 (set_attr "predicable" "yes")])
11484
11485 ;; ARMv8 CRC32 instructions.
11486 (define_insn "arm_<crc_variant>"
11487 [(set (match_operand:SI 0 "s_register_operand" "=r")
11488 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11489 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11490 CRC))]
11491 "TARGET_CRC32"
11492 "<crc_variant>\\t%0, %1, %2"
11493 [(set_attr "type" "crc")
11494 (set_attr "conds" "unconditional")]
11495 )
11496
11497 ;; Load the load/store double peephole optimizations.
11498 (include "ldrdstrd.md")
11499
11500 ;; Load the load/store multiple patterns
11501 (include "ldmstm.md")
11502
11503 ;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11504 ;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11505 ;; The operands are validated through the load_multiple_operation
11506 ;; match_parallel predicate rather than through constraints so enable it only
11507 ;; after reload.
11508 (define_insn "*load_multiple"
11509 [(match_parallel 0 "load_multiple_operation"
11510 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11511 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11512 ])]
11513 "TARGET_32BIT && reload_completed"
11514 "*
11515 {
11516 arm_output_multireg_pop (operands, /*return_pc=*/false,
11517 /*cond=*/const_true_rtx,
11518 /*reverse=*/false,
11519 /*update=*/false);
11520 return \"\";
11521 }
11522 "
11523 [(set_attr "predicable" "yes")]
11524 )
11525
11526 (define_expand "copysignsf3"
11527 [(match_operand:SF 0 "register_operand")
11528 (match_operand:SF 1 "register_operand")
11529 (match_operand:SF 2 "register_operand")]
11530 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11531 "{
11532 emit_move_insn (operands[0], operands[2]);
11533 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11534 GEN_INT (31), GEN_INT (0),
11535 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11536 DONE;
11537 }"
11538 )
11539
11540 (define_expand "copysigndf3"
11541 [(match_operand:DF 0 "register_operand")
11542 (match_operand:DF 1 "register_operand")
11543 (match_operand:DF 2 "register_operand")]
11544 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11545 "{
11546 rtx op0_low = gen_lowpart (SImode, operands[0]);
11547 rtx op0_high = gen_highpart (SImode, operands[0]);
11548 rtx op1_low = gen_lowpart (SImode, operands[1]);
11549 rtx op1_high = gen_highpart (SImode, operands[1]);
11550 rtx op2_high = gen_highpart (SImode, operands[2]);
11551
11552 rtx scratch1 = gen_reg_rtx (SImode);
11553 rtx scratch2 = gen_reg_rtx (SImode);
11554 emit_move_insn (scratch1, op2_high);
11555 emit_move_insn (scratch2, op1_high);
11556
11557 emit_insn(gen_rtx_SET(scratch1,
11558 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11559 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11560 emit_move_insn (op0_low, op1_low);
11561 emit_move_insn (op0_high, scratch2);
11562
11563 DONE;
11564 }"
11565 )
11566
11567 ;; movmisalign patterns for HImode and SImode.
11568 (define_expand "movmisalign<mode>"
11569 [(match_operand:HSI 0 "general_operand")
11570 (match_operand:HSI 1 "general_operand")]
11571 "unaligned_access"
11572 {
11573 /* This pattern is not permitted to fail during expansion: if both arguments
11574 are non-registers (e.g. memory := constant), force operand 1 into a
11575 register. */
11576 rtx (* gen_unaligned_load)(rtx, rtx);
11577 rtx tmp_dest = operands[0];
11578 if (!s_register_operand (operands[0], <MODE>mode)
11579 && !s_register_operand (operands[1], <MODE>mode))
11580 operands[1] = force_reg (<MODE>mode, operands[1]);
11581
11582 if (<MODE>mode == HImode)
11583 {
11584 gen_unaligned_load = gen_unaligned_loadhiu;
11585 tmp_dest = gen_reg_rtx (SImode);
11586 }
11587 else
11588 gen_unaligned_load = gen_unaligned_loadsi;
11589
11590 if (MEM_P (operands[1]))
11591 {
11592 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11593 if (<MODE>mode == HImode)
11594 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11595 }
11596 else
11597 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11598
11599 DONE;
11600 })
11601
11602 (define_insn "arm_<cdp>"
11603 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11604 (match_operand:SI 1 "immediate_operand" "n")
11605 (match_operand:SI 2 "immediate_operand" "n")
11606 (match_operand:SI 3 "immediate_operand" "n")
11607 (match_operand:SI 4 "immediate_operand" "n")
11608 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11609 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11610 {
11611 arm_const_bounds (operands[0], 0, 16);
11612 arm_const_bounds (operands[1], 0, 16);
11613 arm_const_bounds (operands[2], 0, (1 << 5));
11614 arm_const_bounds (operands[3], 0, (1 << 5));
11615 arm_const_bounds (operands[4], 0, (1 << 5));
11616 arm_const_bounds (operands[5], 0, 8);
11617 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11618 }
11619 [(set_attr "length" "4")
11620 (set_attr "type" "coproc")])
11621
11622 (define_insn "*ldc"
11623 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11624 (match_operand:SI 1 "immediate_operand" "n")
11625 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11626 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11627 {
11628 arm_const_bounds (operands[0], 0, 16);
11629 arm_const_bounds (operands[1], 0, (1 << 5));
11630 return "<ldc>\\tp%c0, CR%c1, %2";
11631 }
11632 [(set_attr "length" "4")
11633 (set_attr "type" "coproc")])
11634
11635 (define_insn "*stc"
11636 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11637 (match_operand:SI 1 "immediate_operand" "n")
11638 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11639 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11640 {
11641 arm_const_bounds (operands[0], 0, 16);
11642 arm_const_bounds (operands[1], 0, (1 << 5));
11643 return "<stc>\\tp%c0, CR%c1, %2";
11644 }
11645 [(set_attr "length" "4")
11646 (set_attr "type" "coproc")])
11647
11648 (define_expand "arm_<ldc>"
11649 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11650 (match_operand:SI 1 "immediate_operand")
11651 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11652 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11653
11654 (define_expand "arm_<stc>"
11655 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11656 (match_operand:SI 1 "immediate_operand")
11657 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11658 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11659
11660 (define_insn "arm_<mcr>"
11661 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11662 (match_operand:SI 1 "immediate_operand" "n")
11663 (match_operand:SI 2 "s_register_operand" "r")
11664 (match_operand:SI 3 "immediate_operand" "n")
11665 (match_operand:SI 4 "immediate_operand" "n")
11666 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11667 (use (match_dup 2))]
11668 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11669 {
11670 arm_const_bounds (operands[0], 0, 16);
11671 arm_const_bounds (operands[1], 0, 8);
11672 arm_const_bounds (operands[3], 0, (1 << 5));
11673 arm_const_bounds (operands[4], 0, (1 << 5));
11674 arm_const_bounds (operands[5], 0, 8);
11675 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
11676 }
11677 [(set_attr "length" "4")
11678 (set_attr "type" "coproc")])
11679
11680 (define_insn "arm_<mrc>"
11681 [(set (match_operand:SI 0 "s_register_operand" "=r")
11682 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
11683 (match_operand:SI 2 "immediate_operand" "n")
11684 (match_operand:SI 3 "immediate_operand" "n")
11685 (match_operand:SI 4 "immediate_operand" "n")
11686 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
11687 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
11688 {
11689 arm_const_bounds (operands[1], 0, 16);
11690 arm_const_bounds (operands[2], 0, 8);
11691 arm_const_bounds (operands[3], 0, (1 << 5));
11692 arm_const_bounds (operands[4], 0, (1 << 5));
11693 arm_const_bounds (operands[5], 0, 8);
11694 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
11695 }
11696 [(set_attr "length" "4")
11697 (set_attr "type" "coproc")])
11698
11699 (define_insn "arm_<mcrr>"
11700 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11701 (match_operand:SI 1 "immediate_operand" "n")
11702 (match_operand:DI 2 "s_register_operand" "r")
11703 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
11704 (use (match_dup 2))]
11705 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
11706 {
11707 arm_const_bounds (operands[0], 0, 16);
11708 arm_const_bounds (operands[1], 0, 8);
11709 arm_const_bounds (operands[3], 0, (1 << 5));
11710 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
11711 }
11712 [(set_attr "length" "4")
11713 (set_attr "type" "coproc")])
11714
11715 (define_insn "arm_<mrrc>"
11716 [(set (match_operand:DI 0 "s_register_operand" "=r")
11717 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
11718 (match_operand:SI 2 "immediate_operand" "n")
11719 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
11720 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
11721 {
11722 arm_const_bounds (operands[1], 0, 16);
11723 arm_const_bounds (operands[2], 0, 8);
11724 arm_const_bounds (operands[3], 0, (1 << 5));
11725 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
11726 }
11727 [(set_attr "length" "4")
11728 (set_attr "type" "coproc")])
11729
11730 (define_expand "speculation_barrier"
11731 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11732 "TARGET_EITHER"
11733 "
11734 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
11735 have a usable barrier (and probably don't need one in practice).
11736 But to be safe if such code is run on later architectures, call a
11737 helper function in libgcc that will do the thing for the active
11738 system. */
11739 if (!(arm_arch7 || arm_arch8))
11740 {
11741 arm_emit_speculation_barrier_function ();
11742 DONE;
11743 }
11744 "
11745 )
11746
11747 ;; Generate a hard speculation barrier when we have not enabled speculation
11748 ;; tracking.
11749 (define_insn "*speculation_barrier_insn"
11750 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11751 "arm_arch7 || arm_arch8"
11752 "isb\;dsb\\tsy"
11753 [(set_attr "type" "block")
11754 (set_attr "length" "8")]
11755 )
11756
11757 ;; Vector bits common to IWMMXT and Neon
11758 (include "vec-common.md")
11759 ;; Load the Intel Wireless Multimedia Extension patterns
11760 (include "iwmmxt.md")
11761 ;; Load the VFP co-processor patterns
11762 (include "vfp.md")
11763 ;; Thumb-1 patterns
11764 (include "thumb1.md")
11765 ;; Thumb-2 patterns
11766 (include "thumb2.md")
11767 ;; Neon patterns
11768 (include "neon.md")
11769 ;; Crypto patterns
11770 (include "crypto.md")
11771 ;; Synchronization Primitives
11772 (include "sync.md")
11773 ;; Fixed-point patterns
11774 (include "arm-fixed.md")