]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/arm.md
[ARM/FDPIC v6 21/24] [ARM] FDPIC: Handle stack-protector combined patterns
[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 the operands 0 and 1 being the same
1599 (define_insn "*arm_mulsi3"
1600 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1601 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1602 (match_operand:SI 1 "s_register_operand" "%0,r")))]
1603 "TARGET_32BIT && !arm_arch6"
1604 "mul%?\\t%0, %2, %1"
1605 [(set_attr "type" "mul")
1606 (set_attr "predicable" "yes")]
1607 )
1608
1609 (define_insn "*arm_mulsi3_v6"
1610 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1611 (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1612 (match_operand:SI 2 "s_register_operand" "l,0,r")))]
1613 "TARGET_32BIT && arm_arch6"
1614 "mul%?\\t%0, %1, %2"
1615 [(set_attr "type" "mul")
1616 (set_attr "predicable" "yes")
1617 (set_attr "arch" "t2,t2,*")
1618 (set_attr "length" "4")
1619 (set_attr "predicable_short_it" "yes,yes,no")]
1620 )
1621
1622 (define_insn "*mulsi3_compare0"
1623 [(set (reg:CC_NOOV CC_REGNUM)
1624 (compare:CC_NOOV (mult:SI
1625 (match_operand:SI 2 "s_register_operand" "r,r")
1626 (match_operand:SI 1 "s_register_operand" "%0,r"))
1627 (const_int 0)))
1628 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1629 (mult:SI (match_dup 2) (match_dup 1)))]
1630 "TARGET_ARM && !arm_arch6"
1631 "muls%?\\t%0, %2, %1"
1632 [(set_attr "conds" "set")
1633 (set_attr "type" "muls")]
1634 )
1635
1636 (define_insn "*mulsi3_compare0_v6"
1637 [(set (reg:CC_NOOV CC_REGNUM)
1638 (compare:CC_NOOV (mult:SI
1639 (match_operand:SI 2 "s_register_operand" "r")
1640 (match_operand:SI 1 "s_register_operand" "r"))
1641 (const_int 0)))
1642 (set (match_operand:SI 0 "s_register_operand" "=r")
1643 (mult:SI (match_dup 2) (match_dup 1)))]
1644 "TARGET_ARM && arm_arch6 && optimize_size"
1645 "muls%?\\t%0, %2, %1"
1646 [(set_attr "conds" "set")
1647 (set_attr "type" "muls")]
1648 )
1649
1650 (define_insn "*mulsi_compare0_scratch"
1651 [(set (reg:CC_NOOV CC_REGNUM)
1652 (compare:CC_NOOV (mult:SI
1653 (match_operand:SI 2 "s_register_operand" "r,r")
1654 (match_operand:SI 1 "s_register_operand" "%0,r"))
1655 (const_int 0)))
1656 (clobber (match_scratch:SI 0 "=&r,&r"))]
1657 "TARGET_ARM && !arm_arch6"
1658 "muls%?\\t%0, %2, %1"
1659 [(set_attr "conds" "set")
1660 (set_attr "type" "muls")]
1661 )
1662
1663 (define_insn "*mulsi_compare0_scratch_v6"
1664 [(set (reg:CC_NOOV CC_REGNUM)
1665 (compare:CC_NOOV (mult:SI
1666 (match_operand:SI 2 "s_register_operand" "r")
1667 (match_operand:SI 1 "s_register_operand" "r"))
1668 (const_int 0)))
1669 (clobber (match_scratch:SI 0 "=r"))]
1670 "TARGET_ARM && arm_arch6 && optimize_size"
1671 "muls%?\\t%0, %2, %1"
1672 [(set_attr "conds" "set")
1673 (set_attr "type" "muls")]
1674 )
1675
1676 ;; Unnamed templates to match MLA instruction.
1677
1678 (define_insn "*mulsi3addsi"
1679 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1680 (plus:SI
1681 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1682 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1683 (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1684 "TARGET_32BIT && !arm_arch6"
1685 "mla%?\\t%0, %2, %1, %3"
1686 [(set_attr "type" "mla")
1687 (set_attr "predicable" "yes")]
1688 )
1689
1690 (define_insn "*mulsi3addsi_v6"
1691 [(set (match_operand:SI 0 "s_register_operand" "=r")
1692 (plus:SI
1693 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1694 (match_operand:SI 1 "s_register_operand" "r"))
1695 (match_operand:SI 3 "s_register_operand" "r")))]
1696 "TARGET_32BIT && arm_arch6"
1697 "mla%?\\t%0, %2, %1, %3"
1698 [(set_attr "type" "mla")
1699 (set_attr "predicable" "yes")]
1700 )
1701
1702 (define_insn "*mulsi3addsi_compare0"
1703 [(set (reg:CC_NOOV CC_REGNUM)
1704 (compare:CC_NOOV
1705 (plus:SI (mult:SI
1706 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1707 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1708 (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1709 (const_int 0)))
1710 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1711 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1712 (match_dup 3)))]
1713 "TARGET_ARM && arm_arch6"
1714 "mlas%?\\t%0, %2, %1, %3"
1715 [(set_attr "conds" "set")
1716 (set_attr "type" "mlas")]
1717 )
1718
1719 (define_insn "*mulsi3addsi_compare0_v6"
1720 [(set (reg:CC_NOOV CC_REGNUM)
1721 (compare:CC_NOOV
1722 (plus:SI (mult:SI
1723 (match_operand:SI 2 "s_register_operand" "r")
1724 (match_operand:SI 1 "s_register_operand" "r"))
1725 (match_operand:SI 3 "s_register_operand" "r"))
1726 (const_int 0)))
1727 (set (match_operand:SI 0 "s_register_operand" "=r")
1728 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1729 (match_dup 3)))]
1730 "TARGET_ARM && arm_arch6 && optimize_size"
1731 "mlas%?\\t%0, %2, %1, %3"
1732 [(set_attr "conds" "set")
1733 (set_attr "type" "mlas")]
1734 )
1735
1736 (define_insn "*mulsi3addsi_compare0_scratch"
1737 [(set (reg:CC_NOOV CC_REGNUM)
1738 (compare:CC_NOOV
1739 (plus:SI (mult:SI
1740 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1741 (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1742 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1743 (const_int 0)))
1744 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1745 "TARGET_ARM && !arm_arch6"
1746 "mlas%?\\t%0, %2, %1, %3"
1747 [(set_attr "conds" "set")
1748 (set_attr "type" "mlas")]
1749 )
1750
1751 (define_insn "*mulsi3addsi_compare0_scratch_v6"
1752 [(set (reg:CC_NOOV CC_REGNUM)
1753 (compare:CC_NOOV
1754 (plus:SI (mult:SI
1755 (match_operand:SI 2 "s_register_operand" "r")
1756 (match_operand:SI 1 "s_register_operand" "r"))
1757 (match_operand:SI 3 "s_register_operand" "r"))
1758 (const_int 0)))
1759 (clobber (match_scratch:SI 0 "=r"))]
1760 "TARGET_ARM && arm_arch6 && optimize_size"
1761 "mlas%?\\t%0, %2, %1, %3"
1762 [(set_attr "conds" "set")
1763 (set_attr "type" "mlas")]
1764 )
1765
1766 (define_insn "*mulsi3subsi"
1767 [(set (match_operand:SI 0 "s_register_operand" "=r")
1768 (minus:SI
1769 (match_operand:SI 3 "s_register_operand" "r")
1770 (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1771 (match_operand:SI 1 "s_register_operand" "r"))))]
1772 "TARGET_32BIT && arm_arch_thumb2"
1773 "mls%?\\t%0, %2, %1, %3"
1774 [(set_attr "type" "mla")
1775 (set_attr "predicable" "yes")]
1776 )
1777
1778 (define_expand "maddsidi4"
1779 [(set (match_operand:DI 0 "s_register_operand")
1780 (plus:DI
1781 (mult:DI
1782 (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
1783 (sign_extend:DI (match_operand:SI 2 "s_register_operand")))
1784 (match_operand:DI 3 "s_register_operand")))]
1785 "TARGET_32BIT"
1786 "")
1787
1788 (define_insn "*mulsidi3adddi"
1789 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1790 (plus:DI
1791 (mult:DI
1792 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1793 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1794 (match_operand:DI 1 "s_register_operand" "0")))]
1795 "TARGET_32BIT && !arm_arch6"
1796 "smlal%?\\t%Q0, %R0, %3, %2"
1797 [(set_attr "type" "smlal")
1798 (set_attr "predicable" "yes")]
1799 )
1800
1801 (define_insn "*mulsidi3adddi_v6"
1802 [(set (match_operand:DI 0 "s_register_operand" "=r")
1803 (plus:DI
1804 (mult:DI
1805 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1806 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1807 (match_operand:DI 1 "s_register_operand" "0")))]
1808 "TARGET_32BIT && arm_arch6"
1809 "smlal%?\\t%Q0, %R0, %3, %2"
1810 [(set_attr "type" "smlal")
1811 (set_attr "predicable" "yes")]
1812 )
1813
1814 ;; 32x32->64 widening multiply.
1815 ;; As with mulsi3, the only difference between the v3-5 and v6+
1816 ;; versions of these patterns is the requirement that the output not
1817 ;; overlap the inputs, but that still means we have to have a named
1818 ;; expander and two different starred insns.
1819
1820 (define_expand "mulsidi3"
1821 [(set (match_operand:DI 0 "s_register_operand")
1822 (mult:DI
1823 (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
1824 (sign_extend:DI (match_operand:SI 2 "s_register_operand"))))]
1825 "TARGET_32BIT"
1826 ""
1827 )
1828
1829 (define_insn "*mulsidi3_nov6"
1830 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1831 (mult:DI
1832 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1833 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1834 "TARGET_32BIT && !arm_arch6"
1835 "smull%?\\t%Q0, %R0, %1, %2"
1836 [(set_attr "type" "smull")
1837 (set_attr "predicable" "yes")]
1838 )
1839
1840 (define_insn "*mulsidi3_v6"
1841 [(set (match_operand:DI 0 "s_register_operand" "=r")
1842 (mult:DI
1843 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1844 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1845 "TARGET_32BIT && arm_arch6"
1846 "smull%?\\t%Q0, %R0, %1, %2"
1847 [(set_attr "type" "smull")
1848 (set_attr "predicable" "yes")]
1849 )
1850
1851 (define_expand "umulsidi3"
1852 [(set (match_operand:DI 0 "s_register_operand")
1853 (mult:DI
1854 (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
1855 (zero_extend:DI (match_operand:SI 2 "s_register_operand"))))]
1856 "TARGET_32BIT"
1857 ""
1858 )
1859
1860 (define_insn "*umulsidi3_nov6"
1861 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1862 (mult:DI
1863 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1864 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1865 "TARGET_32BIT && !arm_arch6"
1866 "umull%?\\t%Q0, %R0, %1, %2"
1867 [(set_attr "type" "umull")
1868 (set_attr "predicable" "yes")]
1869 )
1870
1871 (define_insn "*umulsidi3_v6"
1872 [(set (match_operand:DI 0 "s_register_operand" "=r")
1873 (mult:DI
1874 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1875 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1876 "TARGET_32BIT && arm_arch6"
1877 "umull%?\\t%Q0, %R0, %1, %2"
1878 [(set_attr "type" "umull")
1879 (set_attr "predicable" "yes")]
1880 )
1881
1882 (define_expand "umaddsidi4"
1883 [(set (match_operand:DI 0 "s_register_operand")
1884 (plus:DI
1885 (mult:DI
1886 (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
1887 (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
1888 (match_operand:DI 3 "s_register_operand")))]
1889 "TARGET_32BIT"
1890 "")
1891
1892 (define_insn "*umulsidi3adddi"
1893 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1894 (plus:DI
1895 (mult:DI
1896 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1897 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1898 (match_operand:DI 1 "s_register_operand" "0")))]
1899 "TARGET_32BIT && !arm_arch6"
1900 "umlal%?\\t%Q0, %R0, %3, %2"
1901 [(set_attr "type" "umlal")
1902 (set_attr "predicable" "yes")]
1903 )
1904
1905 (define_insn "*umulsidi3adddi_v6"
1906 [(set (match_operand:DI 0 "s_register_operand" "=r")
1907 (plus:DI
1908 (mult:DI
1909 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1910 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1911 (match_operand:DI 1 "s_register_operand" "0")))]
1912 "TARGET_32BIT && arm_arch6"
1913 "umlal%?\\t%Q0, %R0, %3, %2"
1914 [(set_attr "type" "umlal")
1915 (set_attr "predicable" "yes")]
1916 )
1917
1918 (define_expand "smulsi3_highpart"
1919 [(parallel
1920 [(set (match_operand:SI 0 "s_register_operand")
1921 (truncate:SI
1922 (lshiftrt:DI
1923 (mult:DI
1924 (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
1925 (sign_extend:DI (match_operand:SI 2 "s_register_operand")))
1926 (const_int 32))))
1927 (clobber (match_scratch:SI 3 ""))])]
1928 "TARGET_32BIT"
1929 ""
1930 )
1931
1932 (define_insn "*smulsi3_highpart_nov6"
1933 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1934 (truncate:SI
1935 (lshiftrt:DI
1936 (mult:DI
1937 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1938 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1939 (const_int 32))))
1940 (clobber (match_scratch:SI 3 "=&r,&r"))]
1941 "TARGET_32BIT && !arm_arch6"
1942 "smull%?\\t%3, %0, %2, %1"
1943 [(set_attr "type" "smull")
1944 (set_attr "predicable" "yes")]
1945 )
1946
1947 (define_insn "*smulsi3_highpart_v6"
1948 [(set (match_operand:SI 0 "s_register_operand" "=r")
1949 (truncate:SI
1950 (lshiftrt:DI
1951 (mult:DI
1952 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1953 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1954 (const_int 32))))
1955 (clobber (match_scratch:SI 3 "=r"))]
1956 "TARGET_32BIT && arm_arch6"
1957 "smull%?\\t%3, %0, %2, %1"
1958 [(set_attr "type" "smull")
1959 (set_attr "predicable" "yes")]
1960 )
1961
1962 (define_expand "umulsi3_highpart"
1963 [(parallel
1964 [(set (match_operand:SI 0 "s_register_operand")
1965 (truncate:SI
1966 (lshiftrt:DI
1967 (mult:DI
1968 (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
1969 (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
1970 (const_int 32))))
1971 (clobber (match_scratch:SI 3 ""))])]
1972 "TARGET_32BIT"
1973 ""
1974 )
1975
1976 (define_insn "*umulsi3_highpart_nov6"
1977 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1978 (truncate:SI
1979 (lshiftrt:DI
1980 (mult:DI
1981 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1982 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1983 (const_int 32))))
1984 (clobber (match_scratch:SI 3 "=&r,&r"))]
1985 "TARGET_32BIT && !arm_arch6"
1986 "umull%?\\t%3, %0, %2, %1"
1987 [(set_attr "type" "umull")
1988 (set_attr "predicable" "yes")]
1989 )
1990
1991 (define_insn "*umulsi3_highpart_v6"
1992 [(set (match_operand:SI 0 "s_register_operand" "=r")
1993 (truncate:SI
1994 (lshiftrt:DI
1995 (mult:DI
1996 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1997 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1998 (const_int 32))))
1999 (clobber (match_scratch:SI 3 "=r"))]
2000 "TARGET_32BIT && arm_arch6"
2001 "umull%?\\t%3, %0, %2, %1"
2002 [(set_attr "type" "umull")
2003 (set_attr "predicable" "yes")]
2004 )
2005
2006 (define_insn "mulhisi3"
2007 [(set (match_operand:SI 0 "s_register_operand" "=r")
2008 (mult:SI (sign_extend:SI
2009 (match_operand:HI 1 "s_register_operand" "%r"))
2010 (sign_extend:SI
2011 (match_operand:HI 2 "s_register_operand" "r"))))]
2012 "TARGET_DSP_MULTIPLY"
2013 "smulbb%?\\t%0, %1, %2"
2014 [(set_attr "type" "smulxy")
2015 (set_attr "predicable" "yes")]
2016 )
2017
2018 (define_insn "*mulhisi3tb"
2019 [(set (match_operand:SI 0 "s_register_operand" "=r")
2020 (mult:SI (ashiftrt:SI
2021 (match_operand:SI 1 "s_register_operand" "r")
2022 (const_int 16))
2023 (sign_extend:SI
2024 (match_operand:HI 2 "s_register_operand" "r"))))]
2025 "TARGET_DSP_MULTIPLY"
2026 "smultb%?\\t%0, %1, %2"
2027 [(set_attr "type" "smulxy")
2028 (set_attr "predicable" "yes")]
2029 )
2030
2031 (define_insn "*mulhisi3bt"
2032 [(set (match_operand:SI 0 "s_register_operand" "=r")
2033 (mult:SI (sign_extend:SI
2034 (match_operand:HI 1 "s_register_operand" "r"))
2035 (ashiftrt:SI
2036 (match_operand:SI 2 "s_register_operand" "r")
2037 (const_int 16))))]
2038 "TARGET_DSP_MULTIPLY"
2039 "smulbt%?\\t%0, %1, %2"
2040 [(set_attr "type" "smulxy")
2041 (set_attr "predicable" "yes")]
2042 )
2043
2044 (define_insn "*mulhisi3tt"
2045 [(set (match_operand:SI 0 "s_register_operand" "=r")
2046 (mult:SI (ashiftrt:SI
2047 (match_operand:SI 1 "s_register_operand" "r")
2048 (const_int 16))
2049 (ashiftrt:SI
2050 (match_operand:SI 2 "s_register_operand" "r")
2051 (const_int 16))))]
2052 "TARGET_DSP_MULTIPLY"
2053 "smultt%?\\t%0, %1, %2"
2054 [(set_attr "type" "smulxy")
2055 (set_attr "predicable" "yes")]
2056 )
2057
2058 (define_insn "maddhisi4"
2059 [(set (match_operand:SI 0 "s_register_operand" "=r")
2060 (plus:SI (mult:SI (sign_extend:SI
2061 (match_operand:HI 1 "s_register_operand" "r"))
2062 (sign_extend:SI
2063 (match_operand:HI 2 "s_register_operand" "r")))
2064 (match_operand:SI 3 "s_register_operand" "r")))]
2065 "TARGET_DSP_MULTIPLY"
2066 "smlabb%?\\t%0, %1, %2, %3"
2067 [(set_attr "type" "smlaxy")
2068 (set_attr "predicable" "yes")]
2069 )
2070
2071 ;; Note: there is no maddhisi4ibt because this one is canonical form
2072 (define_insn "*maddhisi4tb"
2073 [(set (match_operand:SI 0 "s_register_operand" "=r")
2074 (plus:SI (mult:SI (ashiftrt:SI
2075 (match_operand:SI 1 "s_register_operand" "r")
2076 (const_int 16))
2077 (sign_extend:SI
2078 (match_operand:HI 2 "s_register_operand" "r")))
2079 (match_operand:SI 3 "s_register_operand" "r")))]
2080 "TARGET_DSP_MULTIPLY"
2081 "smlatb%?\\t%0, %1, %2, %3"
2082 [(set_attr "type" "smlaxy")
2083 (set_attr "predicable" "yes")]
2084 )
2085
2086 (define_insn "*maddhisi4tt"
2087 [(set (match_operand:SI 0 "s_register_operand" "=r")
2088 (plus:SI (mult:SI (ashiftrt:SI
2089 (match_operand:SI 1 "s_register_operand" "r")
2090 (const_int 16))
2091 (ashiftrt:SI
2092 (match_operand:SI 2 "s_register_operand" "r")
2093 (const_int 16)))
2094 (match_operand:SI 3 "s_register_operand" "r")))]
2095 "TARGET_DSP_MULTIPLY"
2096 "smlatt%?\\t%0, %1, %2, %3"
2097 [(set_attr "type" "smlaxy")
2098 (set_attr "predicable" "yes")]
2099 )
2100
2101 (define_insn "maddhidi4"
2102 [(set (match_operand:DI 0 "s_register_operand" "=r")
2103 (plus:DI
2104 (mult:DI (sign_extend:DI
2105 (match_operand:HI 1 "s_register_operand" "r"))
2106 (sign_extend:DI
2107 (match_operand:HI 2 "s_register_operand" "r")))
2108 (match_operand:DI 3 "s_register_operand" "0")))]
2109 "TARGET_DSP_MULTIPLY"
2110 "smlalbb%?\\t%Q0, %R0, %1, %2"
2111 [(set_attr "type" "smlalxy")
2112 (set_attr "predicable" "yes")])
2113
2114 ;; Note: there is no maddhidi4ibt because this one is canonical form
2115 (define_insn "*maddhidi4tb"
2116 [(set (match_operand:DI 0 "s_register_operand" "=r")
2117 (plus:DI
2118 (mult:DI (sign_extend:DI
2119 (ashiftrt:SI
2120 (match_operand:SI 1 "s_register_operand" "r")
2121 (const_int 16)))
2122 (sign_extend:DI
2123 (match_operand:HI 2 "s_register_operand" "r")))
2124 (match_operand:DI 3 "s_register_operand" "0")))]
2125 "TARGET_DSP_MULTIPLY"
2126 "smlaltb%?\\t%Q0, %R0, %1, %2"
2127 [(set_attr "type" "smlalxy")
2128 (set_attr "predicable" "yes")])
2129
2130 (define_insn "*maddhidi4tt"
2131 [(set (match_operand:DI 0 "s_register_operand" "=r")
2132 (plus:DI
2133 (mult:DI (sign_extend:DI
2134 (ashiftrt:SI
2135 (match_operand:SI 1 "s_register_operand" "r")
2136 (const_int 16)))
2137 (sign_extend:DI
2138 (ashiftrt:SI
2139 (match_operand:SI 2 "s_register_operand" "r")
2140 (const_int 16))))
2141 (match_operand:DI 3 "s_register_operand" "0")))]
2142 "TARGET_DSP_MULTIPLY"
2143 "smlaltt%?\\t%Q0, %R0, %1, %2"
2144 [(set_attr "type" "smlalxy")
2145 (set_attr "predicable" "yes")])
2146
2147 (define_expand "mulsf3"
2148 [(set (match_operand:SF 0 "s_register_operand")
2149 (mult:SF (match_operand:SF 1 "s_register_operand")
2150 (match_operand:SF 2 "s_register_operand")))]
2151 "TARGET_32BIT && TARGET_HARD_FLOAT"
2152 "
2153 ")
2154
2155 (define_expand "muldf3"
2156 [(set (match_operand:DF 0 "s_register_operand")
2157 (mult:DF (match_operand:DF 1 "s_register_operand")
2158 (match_operand:DF 2 "s_register_operand")))]
2159 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
2160 "
2161 ")
2162 \f
2163 ;; Division insns
2164
2165 (define_expand "divsf3"
2166 [(set (match_operand:SF 0 "s_register_operand")
2167 (div:SF (match_operand:SF 1 "s_register_operand")
2168 (match_operand:SF 2 "s_register_operand")))]
2169 "TARGET_32BIT && TARGET_HARD_FLOAT"
2170 "")
2171
2172 (define_expand "divdf3"
2173 [(set (match_operand:DF 0 "s_register_operand")
2174 (div:DF (match_operand:DF 1 "s_register_operand")
2175 (match_operand:DF 2 "s_register_operand")))]
2176 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
2177 "")
2178 \f
2179
2180 ;; Split DImode and, ior, xor operations. Simply perform the logical
2181 ;; operation on the upper and lower halves of the registers.
2182 ;; This is needed for atomic operations in arm_split_atomic_op.
2183 ;; Avoid splitting IWMMXT instructions.
2184 (define_split
2185 [(set (match_operand:DI 0 "s_register_operand" "")
2186 (match_operator:DI 6 "logical_binary_operator"
2187 [(match_operand:DI 1 "s_register_operand" "")
2188 (match_operand:DI 2 "s_register_operand" "")]))]
2189 "TARGET_32BIT && reload_completed
2190 && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2191 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2192 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
2193 "
2194 {
2195 operands[3] = gen_highpart (SImode, operands[0]);
2196 operands[0] = gen_lowpart (SImode, operands[0]);
2197 operands[4] = gen_highpart (SImode, operands[1]);
2198 operands[1] = gen_lowpart (SImode, operands[1]);
2199 operands[5] = gen_highpart (SImode, operands[2]);
2200 operands[2] = gen_lowpart (SImode, operands[2]);
2201 }"
2202 )
2203
2204 ;; Split DImode not (needed for atomic operations in arm_split_atomic_op).
2205 ;; Unconditionally split since there is no SIMD DImode NOT pattern.
2206 (define_split
2207 [(set (match_operand:DI 0 "s_register_operand")
2208 (not:DI (match_operand:DI 1 "s_register_operand")))]
2209 "TARGET_32BIT"
2210 [(set (match_dup 0) (not:SI (match_dup 1)))
2211 (set (match_dup 2) (not:SI (match_dup 3)))]
2212 "
2213 {
2214 operands[2] = gen_highpart (SImode, operands[0]);
2215 operands[0] = gen_lowpart (SImode, operands[0]);
2216 operands[3] = gen_highpart (SImode, operands[1]);
2217 operands[1] = gen_lowpart (SImode, operands[1]);
2218 }"
2219 )
2220
2221 (define_expand "andsi3"
2222 [(set (match_operand:SI 0 "s_register_operand")
2223 (and:SI (match_operand:SI 1 "s_register_operand")
2224 (match_operand:SI 2 "reg_or_int_operand")))]
2225 "TARGET_EITHER"
2226 "
2227 if (TARGET_32BIT)
2228 {
2229 if (CONST_INT_P (operands[2]))
2230 {
2231 if (INTVAL (operands[2]) == 255 && arm_arch6)
2232 {
2233 operands[1] = convert_to_mode (QImode, operands[1], 1);
2234 emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2235 operands[1]));
2236 DONE;
2237 }
2238 else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
2239 operands[2] = force_reg (SImode, operands[2]);
2240 else
2241 {
2242 arm_split_constant (AND, SImode, NULL_RTX,
2243 INTVAL (operands[2]), operands[0],
2244 operands[1],
2245 optimize && can_create_pseudo_p ());
2246
2247 DONE;
2248 }
2249 }
2250 }
2251 else /* TARGET_THUMB1 */
2252 {
2253 if (!CONST_INT_P (operands[2]))
2254 {
2255 rtx tmp = force_reg (SImode, operands[2]);
2256 if (rtx_equal_p (operands[0], operands[1]))
2257 operands[2] = tmp;
2258 else
2259 {
2260 operands[2] = operands[1];
2261 operands[1] = tmp;
2262 }
2263 }
2264 else
2265 {
2266 int i;
2267
2268 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2269 {
2270 operands[2] = force_reg (SImode,
2271 GEN_INT (~INTVAL (operands[2])));
2272
2273 emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2274
2275 DONE;
2276 }
2277
2278 for (i = 9; i <= 31; i++)
2279 {
2280 if ((HOST_WIDE_INT_1 << i) - 1 == INTVAL (operands[2]))
2281 {
2282 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2283 const0_rtx));
2284 DONE;
2285 }
2286 else if ((HOST_WIDE_INT_1 << i) - 1
2287 == ~INTVAL (operands[2]))
2288 {
2289 rtx shift = GEN_INT (i);
2290 rtx reg = gen_reg_rtx (SImode);
2291
2292 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2293 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2294
2295 DONE;
2296 }
2297 }
2298
2299 operands[2] = force_reg (SImode, operands[2]);
2300 }
2301 }
2302 "
2303 )
2304
2305 ; ??? Check split length for Thumb-2
2306 (define_insn_and_split "*arm_andsi3_insn"
2307 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2308 (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2309 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
2310 "TARGET_32BIT"
2311 "@
2312 and%?\\t%0, %1, %2
2313 and%?\\t%0, %1, %2
2314 bic%?\\t%0, %1, #%B2
2315 and%?\\t%0, %1, %2
2316 #"
2317 "TARGET_32BIT
2318 && CONST_INT_P (operands[2])
2319 && !(const_ok_for_arm (INTVAL (operands[2]))
2320 || const_ok_for_arm (~INTVAL (operands[2])))"
2321 [(clobber (const_int 0))]
2322 "
2323 arm_split_constant (AND, SImode, curr_insn,
2324 INTVAL (operands[2]), operands[0], operands[1], 0);
2325 DONE;
2326 "
2327 [(set_attr "length" "4,4,4,4,16")
2328 (set_attr "predicable" "yes")
2329 (set_attr "predicable_short_it" "no,yes,no,no,no")
2330 (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
2331 )
2332
2333 (define_insn "*andsi3_compare0"
2334 [(set (reg:CC_NOOV CC_REGNUM)
2335 (compare:CC_NOOV
2336 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2337 (match_operand:SI 2 "arm_not_operand" "I,K,r"))
2338 (const_int 0)))
2339 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2340 (and:SI (match_dup 1) (match_dup 2)))]
2341 "TARGET_32BIT"
2342 "@
2343 ands%?\\t%0, %1, %2
2344 bics%?\\t%0, %1, #%B2
2345 ands%?\\t%0, %1, %2"
2346 [(set_attr "conds" "set")
2347 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2348 )
2349
2350 (define_insn "*andsi3_compare0_scratch"
2351 [(set (reg:CC_NOOV CC_REGNUM)
2352 (compare:CC_NOOV
2353 (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2354 (match_operand:SI 1 "arm_not_operand" "I,K,r"))
2355 (const_int 0)))
2356 (clobber (match_scratch:SI 2 "=X,r,X"))]
2357 "TARGET_32BIT"
2358 "@
2359 tst%?\\t%0, %1
2360 bics%?\\t%2, %0, #%B1
2361 tst%?\\t%0, %1"
2362 [(set_attr "conds" "set")
2363 (set_attr "type" "logics_imm,logics_imm,logics_reg")]
2364 )
2365
2366 (define_insn "*zeroextractsi_compare0_scratch"
2367 [(set (reg:CC_NOOV CC_REGNUM)
2368 (compare:CC_NOOV (zero_extract:SI
2369 (match_operand:SI 0 "s_register_operand" "r")
2370 (match_operand 1 "const_int_operand" "n")
2371 (match_operand 2 "const_int_operand" "n"))
2372 (const_int 0)))]
2373 "TARGET_32BIT
2374 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2375 && INTVAL (operands[1]) > 0
2376 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2377 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2378 "*
2379 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2380 << INTVAL (operands[2]));
2381 output_asm_insn (\"tst%?\\t%0, %1\", operands);
2382 return \"\";
2383 "
2384 [(set_attr "conds" "set")
2385 (set_attr "predicable" "yes")
2386 (set_attr "type" "logics_imm")]
2387 )
2388
2389 (define_insn_and_split "*ne_zeroextractsi"
2390 [(set (match_operand:SI 0 "s_register_operand" "=r")
2391 (ne:SI (zero_extract:SI
2392 (match_operand:SI 1 "s_register_operand" "r")
2393 (match_operand:SI 2 "const_int_operand" "n")
2394 (match_operand:SI 3 "const_int_operand" "n"))
2395 (const_int 0)))
2396 (clobber (reg:CC CC_REGNUM))]
2397 "TARGET_32BIT
2398 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2399 && INTVAL (operands[2]) > 0
2400 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2401 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2402 "#"
2403 "TARGET_32BIT
2404 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2405 && INTVAL (operands[2]) > 0
2406 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2407 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2408 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2409 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2410 (const_int 0)))
2411 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2412 (set (match_dup 0)
2413 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2414 (match_dup 0) (const_int 1)))]
2415 "
2416 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2417 << INTVAL (operands[3]));
2418 "
2419 [(set_attr "conds" "clob")
2420 (set (attr "length")
2421 (if_then_else (eq_attr "is_thumb" "yes")
2422 (const_int 12)
2423 (const_int 8)))
2424 (set_attr "type" "multiple")]
2425 )
2426
2427 (define_insn_and_split "*ne_zeroextractsi_shifted"
2428 [(set (match_operand:SI 0 "s_register_operand" "=r")
2429 (ne:SI (zero_extract:SI
2430 (match_operand:SI 1 "s_register_operand" "r")
2431 (match_operand:SI 2 "const_int_operand" "n")
2432 (const_int 0))
2433 (const_int 0)))
2434 (clobber (reg:CC CC_REGNUM))]
2435 "TARGET_ARM"
2436 "#"
2437 "TARGET_ARM"
2438 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2439 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2440 (const_int 0)))
2441 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2442 (set (match_dup 0)
2443 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2444 (match_dup 0) (const_int 1)))]
2445 "
2446 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2447 "
2448 [(set_attr "conds" "clob")
2449 (set_attr "length" "8")
2450 (set_attr "type" "multiple")]
2451 )
2452
2453 (define_insn_and_split "*ite_ne_zeroextractsi"
2454 [(set (match_operand:SI 0 "s_register_operand" "=r")
2455 (if_then_else:SI (ne (zero_extract:SI
2456 (match_operand:SI 1 "s_register_operand" "r")
2457 (match_operand:SI 2 "const_int_operand" "n")
2458 (match_operand:SI 3 "const_int_operand" "n"))
2459 (const_int 0))
2460 (match_operand:SI 4 "arm_not_operand" "rIK")
2461 (const_int 0)))
2462 (clobber (reg:CC CC_REGNUM))]
2463 "TARGET_ARM
2464 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2465 && INTVAL (operands[2]) > 0
2466 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2467 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2468 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2469 "#"
2470 "TARGET_ARM
2471 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2472 && INTVAL (operands[2]) > 0
2473 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2474 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2475 && !reg_overlap_mentioned_p (operands[0], operands[4])"
2476 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2477 (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2478 (const_int 0)))
2479 (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2480 (set (match_dup 0)
2481 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2482 (match_dup 0) (match_dup 4)))]
2483 "
2484 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2485 << INTVAL (operands[3]));
2486 "
2487 [(set_attr "conds" "clob")
2488 (set_attr "length" "8")
2489 (set_attr "type" "multiple")]
2490 )
2491
2492 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2493 [(set (match_operand:SI 0 "s_register_operand" "=r")
2494 (if_then_else:SI (ne (zero_extract:SI
2495 (match_operand:SI 1 "s_register_operand" "r")
2496 (match_operand:SI 2 "const_int_operand" "n")
2497 (const_int 0))
2498 (const_int 0))
2499 (match_operand:SI 3 "arm_not_operand" "rIK")
2500 (const_int 0)))
2501 (clobber (reg:CC CC_REGNUM))]
2502 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2503 "#"
2504 "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2505 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2506 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2507 (const_int 0)))
2508 (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2509 (set (match_dup 0)
2510 (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2511 (match_dup 0) (match_dup 3)))]
2512 "
2513 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2514 "
2515 [(set_attr "conds" "clob")
2516 (set_attr "length" "8")
2517 (set_attr "type" "multiple")]
2518 )
2519
2520 ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2521 (define_split
2522 [(set (match_operand:SI 0 "s_register_operand" "")
2523 (match_operator:SI 1 "shiftable_operator"
2524 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2525 (match_operand:SI 3 "const_int_operand" "")
2526 (match_operand:SI 4 "const_int_operand" ""))
2527 (match_operand:SI 5 "s_register_operand" "")]))
2528 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2529 "TARGET_ARM"
2530 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2531 (set (match_dup 0)
2532 (match_op_dup 1
2533 [(lshiftrt:SI (match_dup 6) (match_dup 4))
2534 (match_dup 5)]))]
2535 "{
2536 HOST_WIDE_INT temp = INTVAL (operands[3]);
2537
2538 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2539 operands[4] = GEN_INT (32 - temp);
2540 }"
2541 )
2542
2543 (define_split
2544 [(set (match_operand:SI 0 "s_register_operand" "")
2545 (match_operator:SI 1 "shiftable_operator"
2546 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2547 (match_operand:SI 3 "const_int_operand" "")
2548 (match_operand:SI 4 "const_int_operand" ""))
2549 (match_operand:SI 5 "s_register_operand" "")]))
2550 (clobber (match_operand:SI 6 "s_register_operand" ""))]
2551 "TARGET_ARM"
2552 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2553 (set (match_dup 0)
2554 (match_op_dup 1
2555 [(ashiftrt:SI (match_dup 6) (match_dup 4))
2556 (match_dup 5)]))]
2557 "{
2558 HOST_WIDE_INT temp = INTVAL (operands[3]);
2559
2560 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2561 operands[4] = GEN_INT (32 - temp);
2562 }"
2563 )
2564
2565 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
2566 ;;; represented by the bitfield, then this will produce incorrect results.
2567 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
2568 ;;; which have a real bit-field insert instruction, the truncation happens
2569 ;;; in the bit-field insert instruction itself. Since arm does not have a
2570 ;;; bit-field insert instruction, we would have to emit code here to truncate
2571 ;;; the value before we insert. This loses some of the advantage of having
2572 ;;; this insv pattern, so this pattern needs to be reevalutated.
2573
2574 (define_expand "insv"
2575 [(set (zero_extract (match_operand 0 "nonimmediate_operand")
2576 (match_operand 1 "general_operand")
2577 (match_operand 2 "general_operand"))
2578 (match_operand 3 "reg_or_int_operand"))]
2579 "TARGET_ARM || arm_arch_thumb2"
2580 "
2581 {
2582 int start_bit = INTVAL (operands[2]);
2583 int width = INTVAL (operands[1]);
2584 HOST_WIDE_INT mask = (HOST_WIDE_INT_1 << width) - 1;
2585 rtx target, subtarget;
2586
2587 if (arm_arch_thumb2)
2588 {
2589 if (unaligned_access && MEM_P (operands[0])
2590 && s_register_operand (operands[3], GET_MODE (operands[3]))
2591 && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
2592 {
2593 rtx base_addr;
2594
2595 if (BYTES_BIG_ENDIAN)
2596 start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2597 - start_bit;
2598
2599 if (width == 32)
2600 {
2601 base_addr = adjust_address (operands[0], SImode,
2602 start_bit / BITS_PER_UNIT);
2603 emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
2604 }
2605 else
2606 {
2607 rtx tmp = gen_reg_rtx (HImode);
2608
2609 base_addr = adjust_address (operands[0], HImode,
2610 start_bit / BITS_PER_UNIT);
2611 emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2612 emit_insn (gen_unaligned_storehi (base_addr, tmp));
2613 }
2614 DONE;
2615 }
2616 else if (s_register_operand (operands[0], GET_MODE (operands[0])))
2617 {
2618 bool use_bfi = TRUE;
2619
2620 if (CONST_INT_P (operands[3]))
2621 {
2622 HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2623
2624 if (val == 0)
2625 {
2626 emit_insn (gen_insv_zero (operands[0], operands[1],
2627 operands[2]));
2628 DONE;
2629 }
2630
2631 /* See if the set can be done with a single orr instruction. */
2632 if (val == mask && const_ok_for_arm (val << start_bit))
2633 use_bfi = FALSE;
2634 }
2635
2636 if (use_bfi)
2637 {
2638 if (!REG_P (operands[3]))
2639 operands[3] = force_reg (SImode, operands[3]);
2640
2641 emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2642 operands[3]));
2643 DONE;
2644 }
2645 }
2646 else
2647 FAIL;
2648 }
2649
2650 if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2651 FAIL;
2652
2653 target = copy_rtx (operands[0]);
2654 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2655 subreg as the final target. */
2656 if (GET_CODE (target) == SUBREG)
2657 {
2658 subtarget = gen_reg_rtx (SImode);
2659 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2660 < GET_MODE_SIZE (SImode))
2661 target = SUBREG_REG (target);
2662 }
2663 else
2664 subtarget = target;
2665
2666 if (CONST_INT_P (operands[3]))
2667 {
2668 /* Since we are inserting a known constant, we may be able to
2669 reduce the number of bits that we have to clear so that
2670 the mask becomes simple. */
2671 /* ??? This code does not check to see if the new mask is actually
2672 simpler. It may not be. */
2673 rtx op1 = gen_reg_rtx (SImode);
2674 /* ??? Truncate operand3 to fit in the bitfield. See comment before
2675 start of this pattern. */
2676 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2677 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2678
2679 emit_insn (gen_andsi3 (op1, operands[0],
2680 gen_int_mode (~mask2, SImode)));
2681 emit_insn (gen_iorsi3 (subtarget, op1,
2682 gen_int_mode (op3_value << start_bit, SImode)));
2683 }
2684 else if (start_bit == 0
2685 && !(const_ok_for_arm (mask)
2686 || const_ok_for_arm (~mask)))
2687 {
2688 /* A Trick, since we are setting the bottom bits in the word,
2689 we can shift operand[3] up, operand[0] down, OR them together
2690 and rotate the result back again. This takes 3 insns, and
2691 the third might be mergeable into another op. */
2692 /* The shift up copes with the possibility that operand[3] is
2693 wider than the bitfield. */
2694 rtx op0 = gen_reg_rtx (SImode);
2695 rtx op1 = gen_reg_rtx (SImode);
2696
2697 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2698 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2699 emit_insn (gen_iorsi3 (op1, op1, op0));
2700 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2701 }
2702 else if ((width + start_bit == 32)
2703 && !(const_ok_for_arm (mask)
2704 || const_ok_for_arm (~mask)))
2705 {
2706 /* Similar trick, but slightly less efficient. */
2707
2708 rtx op0 = gen_reg_rtx (SImode);
2709 rtx op1 = gen_reg_rtx (SImode);
2710
2711 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2712 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2713 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2714 emit_insn (gen_iorsi3 (subtarget, op1, op0));
2715 }
2716 else
2717 {
2718 rtx op0 = gen_int_mode (mask, SImode);
2719 rtx op1 = gen_reg_rtx (SImode);
2720 rtx op2 = gen_reg_rtx (SImode);
2721
2722 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2723 {
2724 rtx tmp = gen_reg_rtx (SImode);
2725
2726 emit_insn (gen_movsi (tmp, op0));
2727 op0 = tmp;
2728 }
2729
2730 /* Mask out any bits in operand[3] that are not needed. */
2731 emit_insn (gen_andsi3 (op1, operands[3], op0));
2732
2733 if (CONST_INT_P (op0)
2734 && (const_ok_for_arm (mask << start_bit)
2735 || const_ok_for_arm (~(mask << start_bit))))
2736 {
2737 op0 = gen_int_mode (~(mask << start_bit), SImode);
2738 emit_insn (gen_andsi3 (op2, operands[0], op0));
2739 }
2740 else
2741 {
2742 if (CONST_INT_P (op0))
2743 {
2744 rtx tmp = gen_reg_rtx (SImode);
2745
2746 emit_insn (gen_movsi (tmp, op0));
2747 op0 = tmp;
2748 }
2749
2750 if (start_bit != 0)
2751 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2752
2753 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2754 }
2755
2756 if (start_bit != 0)
2757 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2758
2759 emit_insn (gen_iorsi3 (subtarget, op1, op2));
2760 }
2761
2762 if (subtarget != target)
2763 {
2764 /* If TARGET is still a SUBREG, then it must be wider than a word,
2765 so we must be careful only to set the subword we were asked to. */
2766 if (GET_CODE (target) == SUBREG)
2767 emit_move_insn (target, subtarget);
2768 else
2769 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2770 }
2771
2772 DONE;
2773 }"
2774 )
2775
2776 (define_insn "insv_zero"
2777 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2778 (match_operand:SI 1 "const_int_M_operand" "M")
2779 (match_operand:SI 2 "const_int_M_operand" "M"))
2780 (const_int 0))]
2781 "arm_arch_thumb2"
2782 "bfc%?\t%0, %2, %1"
2783 [(set_attr "length" "4")
2784 (set_attr "predicable" "yes")
2785 (set_attr "type" "bfm")]
2786 )
2787
2788 (define_insn "insv_t2"
2789 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2790 (match_operand:SI 1 "const_int_M_operand" "M")
2791 (match_operand:SI 2 "const_int_M_operand" "M"))
2792 (match_operand:SI 3 "s_register_operand" "r"))]
2793 "arm_arch_thumb2"
2794 "bfi%?\t%0, %3, %2, %1"
2795 [(set_attr "length" "4")
2796 (set_attr "predicable" "yes")
2797 (set_attr "type" "bfm")]
2798 )
2799
2800 (define_insn "andsi_notsi_si"
2801 [(set (match_operand:SI 0 "s_register_operand" "=r")
2802 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2803 (match_operand:SI 1 "s_register_operand" "r")))]
2804 "TARGET_32BIT"
2805 "bic%?\\t%0, %1, %2"
2806 [(set_attr "predicable" "yes")
2807 (set_attr "type" "logic_reg")]
2808 )
2809
2810 (define_insn "andsi_not_shiftsi_si"
2811 [(set (match_operand:SI 0 "s_register_operand" "=r")
2812 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2813 [(match_operand:SI 2 "s_register_operand" "r")
2814 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2815 (match_operand:SI 1 "s_register_operand" "r")))]
2816 "TARGET_ARM"
2817 "bic%?\\t%0, %1, %2%S4"
2818 [(set_attr "predicable" "yes")
2819 (set_attr "shift" "2")
2820 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2821 (const_string "logic_shift_imm")
2822 (const_string "logic_shift_reg")))]
2823 )
2824
2825 ;; Shifted bics pattern used to set up CC status register and not reusing
2826 ;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
2827 ;; does not support shift by register.
2828 (define_insn "andsi_not_shiftsi_si_scc_no_reuse"
2829 [(set (reg:CC_NOOV CC_REGNUM)
2830 (compare:CC_NOOV
2831 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2832 [(match_operand:SI 1 "s_register_operand" "r")
2833 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2834 (match_operand:SI 3 "s_register_operand" "r"))
2835 (const_int 0)))
2836 (clobber (match_scratch:SI 4 "=r"))]
2837 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
2838 "bics%?\\t%4, %3, %1%S0"
2839 [(set_attr "predicable" "yes")
2840 (set_attr "conds" "set")
2841 (set_attr "shift" "1")
2842 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2843 (const_string "logic_shift_imm")
2844 (const_string "logic_shift_reg")))]
2845 )
2846
2847 ;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
2848 ;; getting reused later.
2849 (define_insn "andsi_not_shiftsi_si_scc"
2850 [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2851 (compare:CC_NOOV
2852 (and:SI (not:SI (match_operator:SI 0 "shift_operator"
2853 [(match_operand:SI 1 "s_register_operand" "r")
2854 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2855 (match_operand:SI 3 "s_register_operand" "r"))
2856 (const_int 0)))
2857 (set (match_operand:SI 4 "s_register_operand" "=r")
2858 (and:SI (not:SI (match_op_dup 0
2859 [(match_dup 1)
2860 (match_dup 2)]))
2861 (match_dup 3)))])]
2862 "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
2863 "bics%?\\t%4, %3, %1%S0"
2864 [(set_attr "predicable" "yes")
2865 (set_attr "conds" "set")
2866 (set_attr "shift" "1")
2867 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2868 (const_string "logic_shift_imm")
2869 (const_string "logic_shift_reg")))]
2870 )
2871
2872 (define_insn "*andsi_notsi_si_compare0"
2873 [(set (reg:CC_NOOV CC_REGNUM)
2874 (compare:CC_NOOV
2875 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2876 (match_operand:SI 1 "s_register_operand" "r"))
2877 (const_int 0)))
2878 (set (match_operand:SI 0 "s_register_operand" "=r")
2879 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2880 "TARGET_32BIT"
2881 "bics\\t%0, %1, %2"
2882 [(set_attr "conds" "set")
2883 (set_attr "type" "logics_shift_reg")]
2884 )
2885
2886 (define_insn "*andsi_notsi_si_compare0_scratch"
2887 [(set (reg:CC_NOOV CC_REGNUM)
2888 (compare:CC_NOOV
2889 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2890 (match_operand:SI 1 "s_register_operand" "r"))
2891 (const_int 0)))
2892 (clobber (match_scratch:SI 0 "=r"))]
2893 "TARGET_32BIT"
2894 "bics\\t%0, %1, %2"
2895 [(set_attr "conds" "set")
2896 (set_attr "type" "logics_shift_reg")]
2897 )
2898
2899 (define_expand "iorsi3"
2900 [(set (match_operand:SI 0 "s_register_operand")
2901 (ior:SI (match_operand:SI 1 "s_register_operand")
2902 (match_operand:SI 2 "reg_or_int_operand")))]
2903 "TARGET_EITHER"
2904 "
2905 if (CONST_INT_P (operands[2]))
2906 {
2907 if (TARGET_32BIT)
2908 {
2909 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
2910 operands[2] = force_reg (SImode, operands[2]);
2911 else
2912 {
2913 arm_split_constant (IOR, SImode, NULL_RTX,
2914 INTVAL (operands[2]), operands[0],
2915 operands[1],
2916 optimize && can_create_pseudo_p ());
2917 DONE;
2918 }
2919 }
2920 else /* TARGET_THUMB1 */
2921 {
2922 rtx tmp = force_reg (SImode, operands[2]);
2923 if (rtx_equal_p (operands[0], operands[1]))
2924 operands[2] = tmp;
2925 else
2926 {
2927 operands[2] = operands[1];
2928 operands[1] = tmp;
2929 }
2930 }
2931 }
2932 "
2933 )
2934
2935 (define_insn_and_split "*iorsi3_insn"
2936 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2937 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2938 (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
2939 "TARGET_32BIT"
2940 "@
2941 orr%?\\t%0, %1, %2
2942 orr%?\\t%0, %1, %2
2943 orn%?\\t%0, %1, #%B2
2944 orr%?\\t%0, %1, %2
2945 #"
2946 "TARGET_32BIT
2947 && CONST_INT_P (operands[2])
2948 && !(const_ok_for_arm (INTVAL (operands[2]))
2949 || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
2950 [(clobber (const_int 0))]
2951 {
2952 arm_split_constant (IOR, SImode, curr_insn,
2953 INTVAL (operands[2]), operands[0], operands[1], 0);
2954 DONE;
2955 }
2956 [(set_attr "length" "4,4,4,4,16")
2957 (set_attr "arch" "32,t2,t2,32,32")
2958 (set_attr "predicable" "yes")
2959 (set_attr "predicable_short_it" "no,yes,no,no,no")
2960 (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
2961 )
2962
2963 (define_peephole2
2964 [(match_scratch:SI 3 "r")
2965 (set (match_operand:SI 0 "arm_general_register_operand" "")
2966 (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2967 (match_operand:SI 2 "const_int_operand" "")))]
2968 "TARGET_ARM
2969 && !const_ok_for_arm (INTVAL (operands[2]))
2970 && const_ok_for_arm (~INTVAL (operands[2]))"
2971 [(set (match_dup 3) (match_dup 2))
2972 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2973 ""
2974 )
2975
2976 (define_insn "*iorsi3_compare0"
2977 [(set (reg:CC_NOOV CC_REGNUM)
2978 (compare:CC_NOOV
2979 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2980 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2981 (const_int 0)))
2982 (set (match_operand:SI 0 "s_register_operand" "=r,l,r")
2983 (ior:SI (match_dup 1) (match_dup 2)))]
2984 "TARGET_32BIT"
2985 "orrs%?\\t%0, %1, %2"
2986 [(set_attr "conds" "set")
2987 (set_attr "arch" "*,t2,*")
2988 (set_attr "length" "4,2,4")
2989 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
2990 )
2991
2992 (define_insn "*iorsi3_compare0_scratch"
2993 [(set (reg:CC_NOOV CC_REGNUM)
2994 (compare:CC_NOOV
2995 (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r")
2996 (match_operand:SI 2 "arm_rhs_operand" "I,l,r"))
2997 (const_int 0)))
2998 (clobber (match_scratch:SI 0 "=r,l,r"))]
2999 "TARGET_32BIT"
3000 "orrs%?\\t%0, %1, %2"
3001 [(set_attr "conds" "set")
3002 (set_attr "arch" "*,t2,*")
3003 (set_attr "length" "4,2,4")
3004 (set_attr "type" "logics_imm,logics_reg,logics_reg")]
3005 )
3006
3007 (define_expand "xorsi3"
3008 [(set (match_operand:SI 0 "s_register_operand")
3009 (xor:SI (match_operand:SI 1 "s_register_operand")
3010 (match_operand:SI 2 "reg_or_int_operand")))]
3011 "TARGET_EITHER"
3012 "if (CONST_INT_P (operands[2]))
3013 {
3014 if (TARGET_32BIT)
3015 {
3016 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
3017 operands[2] = force_reg (SImode, operands[2]);
3018 else
3019 {
3020 arm_split_constant (XOR, SImode, NULL_RTX,
3021 INTVAL (operands[2]), operands[0],
3022 operands[1],
3023 optimize && can_create_pseudo_p ());
3024 DONE;
3025 }
3026 }
3027 else /* TARGET_THUMB1 */
3028 {
3029 rtx tmp = force_reg (SImode, operands[2]);
3030 if (rtx_equal_p (operands[0], operands[1]))
3031 operands[2] = tmp;
3032 else
3033 {
3034 operands[2] = operands[1];
3035 operands[1] = tmp;
3036 }
3037 }
3038 }"
3039 )
3040
3041 (define_insn_and_split "*arm_xorsi3"
3042 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3043 (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3044 (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
3045 "TARGET_32BIT"
3046 "@
3047 eor%?\\t%0, %1, %2
3048 eor%?\\t%0, %1, %2
3049 eor%?\\t%0, %1, %2
3050 #"
3051 "TARGET_32BIT
3052 && CONST_INT_P (operands[2])
3053 && !const_ok_for_arm (INTVAL (operands[2]))"
3054 [(clobber (const_int 0))]
3055 {
3056 arm_split_constant (XOR, SImode, curr_insn,
3057 INTVAL (operands[2]), operands[0], operands[1], 0);
3058 DONE;
3059 }
3060 [(set_attr "length" "4,4,4,16")
3061 (set_attr "predicable" "yes")
3062 (set_attr "predicable_short_it" "no,yes,no,no")
3063 (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
3064 )
3065
3066 (define_insn "*xorsi3_compare0"
3067 [(set (reg:CC_NOOV CC_REGNUM)
3068 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3069 (match_operand:SI 2 "arm_rhs_operand" "I,r"))
3070 (const_int 0)))
3071 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3072 (xor:SI (match_dup 1) (match_dup 2)))]
3073 "TARGET_32BIT"
3074 "eors%?\\t%0, %1, %2"
3075 [(set_attr "conds" "set")
3076 (set_attr "type" "logics_imm,logics_reg")]
3077 )
3078
3079 (define_insn "*xorsi3_compare0_scratch"
3080 [(set (reg:CC_NOOV CC_REGNUM)
3081 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3082 (match_operand:SI 1 "arm_rhs_operand" "I,r"))
3083 (const_int 0)))]
3084 "TARGET_32BIT"
3085 "teq%?\\t%0, %1"
3086 [(set_attr "conds" "set")
3087 (set_attr "type" "logics_imm,logics_reg")]
3088 )
3089
3090 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3091 ; (NOT D) we can sometimes merge the final NOT into one of the following
3092 ; insns.
3093
3094 (define_split
3095 [(set (match_operand:SI 0 "s_register_operand" "")
3096 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3097 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3098 (match_operand:SI 3 "arm_rhs_operand" "")))
3099 (clobber (match_operand:SI 4 "s_register_operand" ""))]
3100 "TARGET_32BIT"
3101 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3102 (not:SI (match_dup 3))))
3103 (set (match_dup 0) (not:SI (match_dup 4)))]
3104 ""
3105 )
3106
3107 (define_insn_and_split "*andsi_iorsi3_notsi"
3108 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3109 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3110 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3111 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3112 "TARGET_32BIT"
3113 "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3114 "&& reload_completed"
3115 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3116 (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3117 {
3118 /* If operands[3] is a constant make sure to fold the NOT into it
3119 to avoid creating a NOT of a CONST_INT. */
3120 rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3121 if (CONST_INT_P (not_rtx))
3122 {
3123 operands[4] = operands[0];
3124 operands[5] = not_rtx;
3125 }
3126 else
3127 {
3128 operands[5] = operands[0];
3129 operands[4] = not_rtx;
3130 }
3131 }
3132 [(set_attr "length" "8")
3133 (set_attr "ce_count" "2")
3134 (set_attr "predicable" "yes")
3135 (set_attr "type" "multiple")]
3136 )
3137
3138 ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3139 ; insns are available?
3140 (define_split
3141 [(set (match_operand:SI 0 "s_register_operand" "")
3142 (match_operator:SI 1 "logical_binary_operator"
3143 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3144 (match_operand:SI 3 "const_int_operand" "")
3145 (match_operand:SI 4 "const_int_operand" ""))
3146 (match_operator:SI 9 "logical_binary_operator"
3147 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3148 (match_operand:SI 6 "const_int_operand" ""))
3149 (match_operand:SI 7 "s_register_operand" "")])]))
3150 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3151 "TARGET_32BIT
3152 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3153 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3154 [(set (match_dup 8)
3155 (match_op_dup 1
3156 [(ashift:SI (match_dup 2) (match_dup 4))
3157 (match_dup 5)]))
3158 (set (match_dup 0)
3159 (match_op_dup 1
3160 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3161 (match_dup 7)]))]
3162 "
3163 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3164 ")
3165
3166 (define_split
3167 [(set (match_operand:SI 0 "s_register_operand" "")
3168 (match_operator:SI 1 "logical_binary_operator"
3169 [(match_operator:SI 9 "logical_binary_operator"
3170 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3171 (match_operand:SI 6 "const_int_operand" ""))
3172 (match_operand:SI 7 "s_register_operand" "")])
3173 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3174 (match_operand:SI 3 "const_int_operand" "")
3175 (match_operand:SI 4 "const_int_operand" ""))]))
3176 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3177 "TARGET_32BIT
3178 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3179 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3180 [(set (match_dup 8)
3181 (match_op_dup 1
3182 [(ashift:SI (match_dup 2) (match_dup 4))
3183 (match_dup 5)]))
3184 (set (match_dup 0)
3185 (match_op_dup 1
3186 [(lshiftrt:SI (match_dup 8) (match_dup 6))
3187 (match_dup 7)]))]
3188 "
3189 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3190 ")
3191
3192 (define_split
3193 [(set (match_operand:SI 0 "s_register_operand" "")
3194 (match_operator:SI 1 "logical_binary_operator"
3195 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3196 (match_operand:SI 3 "const_int_operand" "")
3197 (match_operand:SI 4 "const_int_operand" ""))
3198 (match_operator:SI 9 "logical_binary_operator"
3199 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3200 (match_operand:SI 6 "const_int_operand" ""))
3201 (match_operand:SI 7 "s_register_operand" "")])]))
3202 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3203 "TARGET_32BIT
3204 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3205 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3206 [(set (match_dup 8)
3207 (match_op_dup 1
3208 [(ashift:SI (match_dup 2) (match_dup 4))
3209 (match_dup 5)]))
3210 (set (match_dup 0)
3211 (match_op_dup 1
3212 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3213 (match_dup 7)]))]
3214 "
3215 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3216 ")
3217
3218 (define_split
3219 [(set (match_operand:SI 0 "s_register_operand" "")
3220 (match_operator:SI 1 "logical_binary_operator"
3221 [(match_operator:SI 9 "logical_binary_operator"
3222 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3223 (match_operand:SI 6 "const_int_operand" ""))
3224 (match_operand:SI 7 "s_register_operand" "")])
3225 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3226 (match_operand:SI 3 "const_int_operand" "")
3227 (match_operand:SI 4 "const_int_operand" ""))]))
3228 (clobber (match_operand:SI 8 "s_register_operand" ""))]
3229 "TARGET_32BIT
3230 && GET_CODE (operands[1]) == GET_CODE (operands[9])
3231 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3232 [(set (match_dup 8)
3233 (match_op_dup 1
3234 [(ashift:SI (match_dup 2) (match_dup 4))
3235 (match_dup 5)]))
3236 (set (match_dup 0)
3237 (match_op_dup 1
3238 [(ashiftrt:SI (match_dup 8) (match_dup 6))
3239 (match_dup 7)]))]
3240 "
3241 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3242 ")
3243 \f
3244
3245 ;; Minimum and maximum insns
3246
3247 (define_expand "smaxsi3"
3248 [(parallel [
3249 (set (match_operand:SI 0 "s_register_operand")
3250 (smax:SI (match_operand:SI 1 "s_register_operand")
3251 (match_operand:SI 2 "arm_rhs_operand")))
3252 (clobber (reg:CC CC_REGNUM))])]
3253 "TARGET_32BIT"
3254 "
3255 if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3256 {
3257 /* No need for a clobber of the condition code register here. */
3258 emit_insn (gen_rtx_SET (operands[0],
3259 gen_rtx_SMAX (SImode, operands[1],
3260 operands[2])));
3261 DONE;
3262 }
3263 ")
3264
3265 (define_insn "*smax_0"
3266 [(set (match_operand:SI 0 "s_register_operand" "=r")
3267 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3268 (const_int 0)))]
3269 "TARGET_32BIT"
3270 "bic%?\\t%0, %1, %1, asr #31"
3271 [(set_attr "predicable" "yes")
3272 (set_attr "type" "logic_shift_reg")]
3273 )
3274
3275 (define_insn "*smax_m1"
3276 [(set (match_operand:SI 0 "s_register_operand" "=r")
3277 (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3278 (const_int -1)))]
3279 "TARGET_32BIT"
3280 "orr%?\\t%0, %1, %1, asr #31"
3281 [(set_attr "predicable" "yes")
3282 (set_attr "type" "logic_shift_reg")]
3283 )
3284
3285 (define_insn_and_split "*arm_smax_insn"
3286 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3287 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3288 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3289 (clobber (reg:CC CC_REGNUM))]
3290 "TARGET_ARM"
3291 "#"
3292 ; cmp\\t%1, %2\;movlt\\t%0, %2
3293 ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3294 "TARGET_ARM"
3295 [(set (reg:CC CC_REGNUM)
3296 (compare:CC (match_dup 1) (match_dup 2)))
3297 (set (match_dup 0)
3298 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3299 (match_dup 1)
3300 (match_dup 2)))]
3301 ""
3302 [(set_attr "conds" "clob")
3303 (set_attr "length" "8,12")
3304 (set_attr "type" "multiple")]
3305 )
3306
3307 (define_expand "sminsi3"
3308 [(parallel [
3309 (set (match_operand:SI 0 "s_register_operand")
3310 (smin:SI (match_operand:SI 1 "s_register_operand")
3311 (match_operand:SI 2 "arm_rhs_operand")))
3312 (clobber (reg:CC CC_REGNUM))])]
3313 "TARGET_32BIT"
3314 "
3315 if (operands[2] == const0_rtx)
3316 {
3317 /* No need for a clobber of the condition code register here. */
3318 emit_insn (gen_rtx_SET (operands[0],
3319 gen_rtx_SMIN (SImode, operands[1],
3320 operands[2])));
3321 DONE;
3322 }
3323 ")
3324
3325 (define_insn "*smin_0"
3326 [(set (match_operand:SI 0 "s_register_operand" "=r")
3327 (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3328 (const_int 0)))]
3329 "TARGET_32BIT"
3330 "and%?\\t%0, %1, %1, asr #31"
3331 [(set_attr "predicable" "yes")
3332 (set_attr "type" "logic_shift_reg")]
3333 )
3334
3335 (define_insn_and_split "*arm_smin_insn"
3336 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3337 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3338 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3339 (clobber (reg:CC CC_REGNUM))]
3340 "TARGET_ARM"
3341 "#"
3342 ; cmp\\t%1, %2\;movge\\t%0, %2
3343 ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3344 "TARGET_ARM"
3345 [(set (reg:CC CC_REGNUM)
3346 (compare:CC (match_dup 1) (match_dup 2)))
3347 (set (match_dup 0)
3348 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3349 (match_dup 1)
3350 (match_dup 2)))]
3351 ""
3352 [(set_attr "conds" "clob")
3353 (set_attr "length" "8,12")
3354 (set_attr "type" "multiple,multiple")]
3355 )
3356
3357 (define_expand "umaxsi3"
3358 [(parallel [
3359 (set (match_operand:SI 0 "s_register_operand")
3360 (umax:SI (match_operand:SI 1 "s_register_operand")
3361 (match_operand:SI 2 "arm_rhs_operand")))
3362 (clobber (reg:CC CC_REGNUM))])]
3363 "TARGET_32BIT"
3364 ""
3365 )
3366
3367 (define_insn_and_split "*arm_umaxsi3"
3368 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3369 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3370 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3371 (clobber (reg:CC CC_REGNUM))]
3372 "TARGET_ARM"
3373 "#"
3374 ; cmp\\t%1, %2\;movcc\\t%0, %2
3375 ; cmp\\t%1, %2\;movcs\\t%0, %1
3376 ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3377 "TARGET_ARM"
3378 [(set (reg:CC CC_REGNUM)
3379 (compare:CC (match_dup 1) (match_dup 2)))
3380 (set (match_dup 0)
3381 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3382 (match_dup 1)
3383 (match_dup 2)))]
3384 ""
3385 [(set_attr "conds" "clob")
3386 (set_attr "length" "8,8,12")
3387 (set_attr "type" "store_4")]
3388 )
3389
3390 (define_expand "uminsi3"
3391 [(parallel [
3392 (set (match_operand:SI 0 "s_register_operand")
3393 (umin:SI (match_operand:SI 1 "s_register_operand")
3394 (match_operand:SI 2 "arm_rhs_operand")))
3395 (clobber (reg:CC CC_REGNUM))])]
3396 "TARGET_32BIT"
3397 ""
3398 )
3399
3400 (define_insn_and_split "*arm_uminsi3"
3401 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3402 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3403 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3404 (clobber (reg:CC CC_REGNUM))]
3405 "TARGET_ARM"
3406 "#"
3407 ; cmp\\t%1, %2\;movcs\\t%0, %2
3408 ; cmp\\t%1, %2\;movcc\\t%0, %1
3409 ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3410 "TARGET_ARM"
3411 [(set (reg:CC CC_REGNUM)
3412 (compare:CC (match_dup 1) (match_dup 2)))
3413 (set (match_dup 0)
3414 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3415 (match_dup 1)
3416 (match_dup 2)))]
3417 ""
3418 [(set_attr "conds" "clob")
3419 (set_attr "length" "8,8,12")
3420 (set_attr "type" "store_4")]
3421 )
3422
3423 (define_insn "*store_minmaxsi"
3424 [(set (match_operand:SI 0 "memory_operand" "=m")
3425 (match_operator:SI 3 "minmax_operator"
3426 [(match_operand:SI 1 "s_register_operand" "r")
3427 (match_operand:SI 2 "s_register_operand" "r")]))
3428 (clobber (reg:CC CC_REGNUM))]
3429 "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
3430 "*
3431 operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3432 operands[1], operands[2]);
3433 output_asm_insn (\"cmp\\t%1, %2\", operands);
3434 if (TARGET_THUMB2)
3435 output_asm_insn (\"ite\t%d3\", operands);
3436 output_asm_insn (\"str%d3\\t%1, %0\", operands);
3437 output_asm_insn (\"str%D3\\t%2, %0\", operands);
3438 return \"\";
3439 "
3440 [(set_attr "conds" "clob")
3441 (set (attr "length")
3442 (if_then_else (eq_attr "is_thumb" "yes")
3443 (const_int 14)
3444 (const_int 12)))
3445 (set_attr "type" "store_4")]
3446 )
3447
3448 ; Reject the frame pointer in operand[1], since reloading this after
3449 ; it has been eliminated can cause carnage.
3450 (define_insn "*minmax_arithsi"
3451 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3452 (match_operator:SI 4 "shiftable_operator"
3453 [(match_operator:SI 5 "minmax_operator"
3454 [(match_operand:SI 2 "s_register_operand" "r,r")
3455 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3456 (match_operand:SI 1 "s_register_operand" "0,?r")]))
3457 (clobber (reg:CC CC_REGNUM))]
3458 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
3459 "*
3460 {
3461 enum rtx_code code = GET_CODE (operands[4]);
3462 bool need_else;
3463
3464 if (which_alternative != 0 || operands[3] != const0_rtx
3465 || (code != PLUS && code != IOR && code != XOR))
3466 need_else = true;
3467 else
3468 need_else = false;
3469
3470 operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3471 operands[2], operands[3]);
3472 output_asm_insn (\"cmp\\t%2, %3\", operands);
3473 if (TARGET_THUMB2)
3474 {
3475 if (need_else)
3476 output_asm_insn (\"ite\\t%d5\", operands);
3477 else
3478 output_asm_insn (\"it\\t%d5\", operands);
3479 }
3480 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3481 if (need_else)
3482 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3483 return \"\";
3484 }"
3485 [(set_attr "conds" "clob")
3486 (set (attr "length")
3487 (if_then_else (eq_attr "is_thumb" "yes")
3488 (const_int 14)
3489 (const_int 12)))
3490 (set_attr "type" "multiple")]
3491 )
3492
3493 ; Reject the frame pointer in operand[1], since reloading this after
3494 ; it has been eliminated can cause carnage.
3495 (define_insn_and_split "*minmax_arithsi_non_canon"
3496 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3497 (minus:SI
3498 (match_operand:SI 1 "s_register_operand" "0,?Ts")
3499 (match_operator:SI 4 "minmax_operator"
3500 [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3501 (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
3502 (clobber (reg:CC CC_REGNUM))]
3503 "TARGET_32BIT && !arm_eliminable_register (operands[1])
3504 && !(arm_restrict_it && CONST_INT_P (operands[3]))"
3505 "#"
3506 "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3507 [(set (reg:CC CC_REGNUM)
3508 (compare:CC (match_dup 2) (match_dup 3)))
3509
3510 (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3511 (set (match_dup 0)
3512 (minus:SI (match_dup 1)
3513 (match_dup 2))))
3514 (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3515 (set (match_dup 0)
3516 (match_dup 6)))]
3517 {
3518 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3519 operands[2], operands[3]);
3520 enum rtx_code rc = minmax_code (operands[4]);
3521 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3522 operands[2], operands[3]);
3523
3524 if (mode == CCFPmode || mode == CCFPEmode)
3525 rc = reverse_condition_maybe_unordered (rc);
3526 else
3527 rc = reverse_condition (rc);
3528 operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
3529 if (CONST_INT_P (operands[3]))
3530 operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3531 else
3532 operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
3533 }
3534 [(set_attr "conds" "clob")
3535 (set (attr "length")
3536 (if_then_else (eq_attr "is_thumb" "yes")
3537 (const_int 14)
3538 (const_int 12)))
3539 (set_attr "type" "multiple")]
3540 )
3541
3542 (define_code_iterator SAT [smin smax])
3543 (define_code_attr SATrev [(smin "smax") (smax "smin")])
3544 (define_code_attr SATlo [(smin "1") (smax "2")])
3545 (define_code_attr SAThi [(smin "2") (smax "1")])
3546
3547 (define_insn "*satsi_<SAT:code>"
3548 [(set (match_operand:SI 0 "s_register_operand" "=r")
3549 (SAT:SI (<SATrev>:SI (match_operand:SI 3 "s_register_operand" "r")
3550 (match_operand:SI 1 "const_int_operand" "i"))
3551 (match_operand:SI 2 "const_int_operand" "i")))]
3552 "TARGET_32BIT && arm_arch6
3553 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3554 {
3555 int mask;
3556 bool signed_sat;
3557 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3558 &mask, &signed_sat))
3559 gcc_unreachable ();
3560
3561 operands[1] = GEN_INT (mask);
3562 if (signed_sat)
3563 return "ssat%?\t%0, %1, %3";
3564 else
3565 return "usat%?\t%0, %1, %3";
3566 }
3567 [(set_attr "predicable" "yes")
3568 (set_attr "type" "alus_imm")]
3569 )
3570
3571 (define_insn "*satsi_<SAT:code>_shift"
3572 [(set (match_operand:SI 0 "s_register_operand" "=r")
3573 (SAT:SI (<SATrev>:SI (match_operator:SI 3 "sat_shift_operator"
3574 [(match_operand:SI 4 "s_register_operand" "r")
3575 (match_operand:SI 5 "const_int_operand" "i")])
3576 (match_operand:SI 1 "const_int_operand" "i"))
3577 (match_operand:SI 2 "const_int_operand" "i")))]
3578 "TARGET_32BIT && arm_arch6
3579 && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3580 {
3581 int mask;
3582 bool signed_sat;
3583 if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3584 &mask, &signed_sat))
3585 gcc_unreachable ();
3586
3587 operands[1] = GEN_INT (mask);
3588 if (signed_sat)
3589 return "ssat%?\t%0, %1, %4%S3";
3590 else
3591 return "usat%?\t%0, %1, %4%S3";
3592 }
3593 [(set_attr "predicable" "yes")
3594 (set_attr "shift" "3")
3595 (set_attr "type" "logic_shift_reg")])
3596 \f
3597 ;; Shift and rotation insns
3598
3599 (define_expand "ashldi3"
3600 [(set (match_operand:DI 0 "s_register_operand")
3601 (ashift:DI (match_operand:DI 1 "s_register_operand")
3602 (match_operand:SI 2 "reg_or_int_operand")))]
3603 "TARGET_32BIT"
3604 "
3605 arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3606 operands[2], gen_reg_rtx (SImode),
3607 gen_reg_rtx (SImode));
3608 DONE;
3609 ")
3610
3611 (define_expand "ashlsi3"
3612 [(set (match_operand:SI 0 "s_register_operand")
3613 (ashift:SI (match_operand:SI 1 "s_register_operand")
3614 (match_operand:SI 2 "arm_rhs_operand")))]
3615 "TARGET_EITHER"
3616 "
3617 if (CONST_INT_P (operands[2])
3618 && (UINTVAL (operands[2])) > 31)
3619 {
3620 emit_insn (gen_movsi (operands[0], const0_rtx));
3621 DONE;
3622 }
3623 "
3624 )
3625
3626 (define_expand "ashrdi3"
3627 [(set (match_operand:DI 0 "s_register_operand")
3628 (ashiftrt:DI (match_operand:DI 1 "s_register_operand")
3629 (match_operand:SI 2 "reg_or_int_operand")))]
3630 "TARGET_32BIT"
3631 "
3632 arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3633 operands[2], gen_reg_rtx (SImode),
3634 gen_reg_rtx (SImode));
3635 DONE;
3636 ")
3637
3638 (define_expand "ashrsi3"
3639 [(set (match_operand:SI 0 "s_register_operand")
3640 (ashiftrt:SI (match_operand:SI 1 "s_register_operand")
3641 (match_operand:SI 2 "arm_rhs_operand")))]
3642 "TARGET_EITHER"
3643 "
3644 if (CONST_INT_P (operands[2])
3645 && UINTVAL (operands[2]) > 31)
3646 operands[2] = GEN_INT (31);
3647 "
3648 )
3649
3650 (define_expand "lshrdi3"
3651 [(set (match_operand:DI 0 "s_register_operand")
3652 (lshiftrt:DI (match_operand:DI 1 "s_register_operand")
3653 (match_operand:SI 2 "reg_or_int_operand")))]
3654 "TARGET_32BIT"
3655 "
3656 arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3657 operands[2], gen_reg_rtx (SImode),
3658 gen_reg_rtx (SImode));
3659 DONE;
3660 ")
3661
3662 (define_expand "lshrsi3"
3663 [(set (match_operand:SI 0 "s_register_operand")
3664 (lshiftrt:SI (match_operand:SI 1 "s_register_operand")
3665 (match_operand:SI 2 "arm_rhs_operand")))]
3666 "TARGET_EITHER"
3667 "
3668 if (CONST_INT_P (operands[2])
3669 && (UINTVAL (operands[2])) > 31)
3670 {
3671 emit_insn (gen_movsi (operands[0], const0_rtx));
3672 DONE;
3673 }
3674 "
3675 )
3676
3677 (define_expand "rotlsi3"
3678 [(set (match_operand:SI 0 "s_register_operand")
3679 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3680 (match_operand:SI 2 "reg_or_int_operand")))]
3681 "TARGET_32BIT"
3682 "
3683 if (CONST_INT_P (operands[2]))
3684 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3685 else
3686 {
3687 rtx reg = gen_reg_rtx (SImode);
3688 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3689 operands[2] = reg;
3690 }
3691 "
3692 )
3693
3694 (define_expand "rotrsi3"
3695 [(set (match_operand:SI 0 "s_register_operand")
3696 (rotatert:SI (match_operand:SI 1 "s_register_operand")
3697 (match_operand:SI 2 "arm_rhs_operand")))]
3698 "TARGET_EITHER"
3699 "
3700 if (TARGET_32BIT)
3701 {
3702 if (CONST_INT_P (operands[2])
3703 && UINTVAL (operands[2]) > 31)
3704 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3705 }
3706 else /* TARGET_THUMB1 */
3707 {
3708 if (CONST_INT_P (operands [2]))
3709 operands [2] = force_reg (SImode, operands[2]);
3710 }
3711 "
3712 )
3713
3714 (define_insn "*arm_shiftsi3"
3715 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
3716 (match_operator:SI 3 "shift_operator"
3717 [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3718 (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
3719 "TARGET_32BIT"
3720 "* return arm_output_shift(operands, 0);"
3721 [(set_attr "predicable" "yes")
3722 (set_attr "arch" "t2,t2,*,*")
3723 (set_attr "predicable_short_it" "yes,yes,no,no")
3724 (set_attr "length" "4")
3725 (set_attr "shift" "1")
3726 (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
3727 )
3728
3729 (define_insn "*shiftsi3_compare0"
3730 [(set (reg:CC_NOOV CC_REGNUM)
3731 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3732 [(match_operand:SI 1 "s_register_operand" "r,r")
3733 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
3734 (const_int 0)))
3735 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3736 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3737 "TARGET_32BIT"
3738 "* return arm_output_shift(operands, 1);"
3739 [(set_attr "conds" "set")
3740 (set_attr "shift" "1")
3741 (set_attr "type" "alus_shift_imm,alus_shift_reg")]
3742 )
3743
3744 (define_insn "*shiftsi3_compare0_scratch"
3745 [(set (reg:CC_NOOV CC_REGNUM)
3746 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3747 [(match_operand:SI 1 "s_register_operand" "r,r")
3748 (match_operand:SI 2 "arm_rhs_operand" "M,r")])
3749 (const_int 0)))
3750 (clobber (match_scratch:SI 0 "=r,r"))]
3751 "TARGET_32BIT"
3752 "* return arm_output_shift(operands, 1);"
3753 [(set_attr "conds" "set")
3754 (set_attr "shift" "1")
3755 (set_attr "type" "shift_imm,shift_reg")]
3756 )
3757
3758 (define_insn "*not_shiftsi"
3759 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3760 (not:SI (match_operator:SI 3 "shift_operator"
3761 [(match_operand:SI 1 "s_register_operand" "r,r")
3762 (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3763 "TARGET_32BIT"
3764 "mvn%?\\t%0, %1%S3"
3765 [(set_attr "predicable" "yes")
3766 (set_attr "shift" "1")
3767 (set_attr "arch" "32,a")
3768 (set_attr "type" "mvn_shift,mvn_shift_reg")])
3769
3770 (define_insn "*not_shiftsi_compare0"
3771 [(set (reg:CC_NOOV CC_REGNUM)
3772 (compare:CC_NOOV
3773 (not:SI (match_operator:SI 3 "shift_operator"
3774 [(match_operand:SI 1 "s_register_operand" "r,r")
3775 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3776 (const_int 0)))
3777 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3778 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3779 "TARGET_32BIT"
3780 "mvns%?\\t%0, %1%S3"
3781 [(set_attr "conds" "set")
3782 (set_attr "shift" "1")
3783 (set_attr "arch" "32,a")
3784 (set_attr "type" "mvn_shift,mvn_shift_reg")])
3785
3786 (define_insn "*not_shiftsi_compare0_scratch"
3787 [(set (reg:CC_NOOV CC_REGNUM)
3788 (compare:CC_NOOV
3789 (not:SI (match_operator:SI 3 "shift_operator"
3790 [(match_operand:SI 1 "s_register_operand" "r,r")
3791 (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3792 (const_int 0)))
3793 (clobber (match_scratch:SI 0 "=r,r"))]
3794 "TARGET_32BIT"
3795 "mvns%?\\t%0, %1%S3"
3796 [(set_attr "conds" "set")
3797 (set_attr "shift" "1")
3798 (set_attr "arch" "32,a")
3799 (set_attr "type" "mvn_shift,mvn_shift_reg")])
3800
3801 ;; We don't really have extzv, but defining this using shifts helps
3802 ;; to reduce register pressure later on.
3803
3804 (define_expand "extzv"
3805 [(set (match_operand 0 "s_register_operand")
3806 (zero_extract (match_operand 1 "nonimmediate_operand")
3807 (match_operand 2 "const_int_operand")
3808 (match_operand 3 "const_int_operand")))]
3809 "TARGET_THUMB1 || arm_arch_thumb2"
3810 "
3811 {
3812 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3813 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3814
3815 if (arm_arch_thumb2)
3816 {
3817 HOST_WIDE_INT width = INTVAL (operands[2]);
3818 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3819
3820 if (unaligned_access && MEM_P (operands[1])
3821 && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3822 {
3823 rtx base_addr;
3824
3825 if (BYTES_BIG_ENDIAN)
3826 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3827 - bitpos;
3828
3829 if (width == 32)
3830 {
3831 base_addr = adjust_address (operands[1], SImode,
3832 bitpos / BITS_PER_UNIT);
3833 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3834 }
3835 else
3836 {
3837 rtx dest = operands[0];
3838 rtx tmp = gen_reg_rtx (SImode);
3839
3840 /* We may get a paradoxical subreg here. Strip it off. */
3841 if (GET_CODE (dest) == SUBREG
3842 && GET_MODE (dest) == SImode
3843 && GET_MODE (SUBREG_REG (dest)) == HImode)
3844 dest = SUBREG_REG (dest);
3845
3846 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3847 FAIL;
3848
3849 base_addr = adjust_address (operands[1], HImode,
3850 bitpos / BITS_PER_UNIT);
3851 emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3852 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3853 }
3854 DONE;
3855 }
3856 else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3857 {
3858 emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3859 operands[3]));
3860 DONE;
3861 }
3862 else
3863 FAIL;
3864 }
3865
3866 if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3867 FAIL;
3868
3869 operands[3] = GEN_INT (rshift);
3870
3871 if (lshift == 0)
3872 {
3873 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3874 DONE;
3875 }
3876
3877 emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3878 operands[3], gen_reg_rtx (SImode)));
3879 DONE;
3880 }"
3881 )
3882
3883 ;; Helper for extzv, for the Thumb-1 register-shifts case.
3884
3885 (define_expand "extzv_t1"
3886 [(set (match_operand:SI 4 "s_register_operand")
3887 (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
3888 (match_operand:SI 2 "const_int_operand")))
3889 (set (match_operand:SI 0 "s_register_operand")
3890 (lshiftrt:SI (match_dup 4)
3891 (match_operand:SI 3 "const_int_operand")))]
3892 "TARGET_THUMB1"
3893 "")
3894
3895 (define_expand "extv"
3896 [(set (match_operand 0 "s_register_operand")
3897 (sign_extract (match_operand 1 "nonimmediate_operand")
3898 (match_operand 2 "const_int_operand")
3899 (match_operand 3 "const_int_operand")))]
3900 "arm_arch_thumb2"
3901 {
3902 HOST_WIDE_INT width = INTVAL (operands[2]);
3903 HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3904
3905 if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3906 && (bitpos % BITS_PER_UNIT) == 0)
3907 {
3908 rtx base_addr;
3909
3910 if (BYTES_BIG_ENDIAN)
3911 bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3912
3913 if (width == 32)
3914 {
3915 base_addr = adjust_address (operands[1], SImode,
3916 bitpos / BITS_PER_UNIT);
3917 emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3918 }
3919 else
3920 {
3921 rtx dest = operands[0];
3922 rtx tmp = gen_reg_rtx (SImode);
3923
3924 /* We may get a paradoxical subreg here. Strip it off. */
3925 if (GET_CODE (dest) == SUBREG
3926 && GET_MODE (dest) == SImode
3927 && GET_MODE (SUBREG_REG (dest)) == HImode)
3928 dest = SUBREG_REG (dest);
3929
3930 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3931 FAIL;
3932
3933 base_addr = adjust_address (operands[1], HImode,
3934 bitpos / BITS_PER_UNIT);
3935 emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3936 emit_move_insn (gen_lowpart (SImode, dest), tmp);
3937 }
3938
3939 DONE;
3940 }
3941 else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3942 FAIL;
3943 else if (GET_MODE (operands[0]) == SImode
3944 && GET_MODE (operands[1]) == SImode)
3945 {
3946 emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3947 operands[3]));
3948 DONE;
3949 }
3950
3951 FAIL;
3952 })
3953
3954 ; Helper to expand register forms of extv with the proper modes.
3955
3956 (define_expand "extv_regsi"
3957 [(set (match_operand:SI 0 "s_register_operand")
3958 (sign_extract:SI (match_operand:SI 1 "s_register_operand")
3959 (match_operand 2 "const_int_operand")
3960 (match_operand 3 "const_int_operand")))]
3961 ""
3962 {
3963 })
3964
3965 ; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3966
3967 (define_insn "unaligned_loaddi"
3968 [(set (match_operand:DI 0 "s_register_operand" "=r")
3969 (unspec:DI [(match_operand:DI 1 "memory_operand" "m")]
3970 UNSPEC_UNALIGNED_LOAD))]
3971 "TARGET_32BIT && TARGET_LDRD"
3972 "*
3973 return output_move_double (operands, true, NULL);
3974 "
3975 [(set_attr "length" "8")
3976 (set_attr "type" "load_8")])
3977
3978 (define_insn "unaligned_loadsi"
3979 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
3980 (unspec:SI [(match_operand:SI 1 "memory_operand" "m,Uw,m")]
3981 UNSPEC_UNALIGNED_LOAD))]
3982 "unaligned_access"
3983 "@
3984 ldr\t%0, %1\t@ unaligned
3985 ldr%?\t%0, %1\t@ unaligned
3986 ldr%?\t%0, %1\t@ unaligned"
3987 [(set_attr "arch" "t1,t2,32")
3988 (set_attr "length" "2,2,4")
3989 (set_attr "predicable" "no,yes,yes")
3990 (set_attr "predicable_short_it" "no,yes,no")
3991 (set_attr "type" "load_4")])
3992
3993 ;; The 16-bit Thumb1 variant of ldrsh requires two registers in the
3994 ;; address (there's no immediate format). That's tricky to support
3995 ;; here and we don't really need this pattern for that case, so only
3996 ;; enable for 32-bit ISAs.
3997 (define_insn "unaligned_loadhis"
3998 [(set (match_operand:SI 0 "s_register_operand" "=r")
3999 (sign_extend:SI
4000 (unspec:HI [(match_operand:HI 1 "memory_operand" "Uh")]
4001 UNSPEC_UNALIGNED_LOAD)))]
4002 "unaligned_access && TARGET_32BIT"
4003 "ldrsh%?\t%0, %1\t@ unaligned"
4004 [(set_attr "predicable" "yes")
4005 (set_attr "type" "load_byte")])
4006
4007 (define_insn "unaligned_loadhiu"
4008 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
4009 (zero_extend:SI
4010 (unspec:HI [(match_operand:HI 1 "memory_operand" "m,Uw,m")]
4011 UNSPEC_UNALIGNED_LOAD)))]
4012 "unaligned_access"
4013 "@
4014 ldrh\t%0, %1\t@ unaligned
4015 ldrh%?\t%0, %1\t@ unaligned
4016 ldrh%?\t%0, %1\t@ unaligned"
4017 [(set_attr "arch" "t1,t2,32")
4018 (set_attr "length" "2,2,4")
4019 (set_attr "predicable" "no,yes,yes")
4020 (set_attr "predicable_short_it" "no,yes,no")
4021 (set_attr "type" "load_byte")])
4022
4023 (define_insn "unaligned_storedi"
4024 [(set (match_operand:DI 0 "memory_operand" "=m")
4025 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")]
4026 UNSPEC_UNALIGNED_STORE))]
4027 "TARGET_32BIT && TARGET_LDRD"
4028 "*
4029 return output_move_double (operands, true, NULL);
4030 "
4031 [(set_attr "length" "8")
4032 (set_attr "type" "store_8")])
4033
4034 (define_insn "unaligned_storesi"
4035 [(set (match_operand:SI 0 "memory_operand" "=m,Uw,m")
4036 (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,l,r")]
4037 UNSPEC_UNALIGNED_STORE))]
4038 "unaligned_access"
4039 "@
4040 str\t%1, %0\t@ unaligned
4041 str%?\t%1, %0\t@ unaligned
4042 str%?\t%1, %0\t@ unaligned"
4043 [(set_attr "arch" "t1,t2,32")
4044 (set_attr "length" "2,2,4")
4045 (set_attr "predicable" "no,yes,yes")
4046 (set_attr "predicable_short_it" "no,yes,no")
4047 (set_attr "type" "store_4")])
4048
4049 (define_insn "unaligned_storehi"
4050 [(set (match_operand:HI 0 "memory_operand" "=m,Uw,m")
4051 (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,l,r")]
4052 UNSPEC_UNALIGNED_STORE))]
4053 "unaligned_access"
4054 "@
4055 strh\t%1, %0\t@ unaligned
4056 strh%?\t%1, %0\t@ unaligned
4057 strh%?\t%1, %0\t@ unaligned"
4058 [(set_attr "arch" "t1,t2,32")
4059 (set_attr "length" "2,2,4")
4060 (set_attr "predicable" "no,yes,yes")
4061 (set_attr "predicable_short_it" "no,yes,no")
4062 (set_attr "type" "store_4")])
4063
4064
4065 (define_insn "*extv_reg"
4066 [(set (match_operand:SI 0 "s_register_operand" "=r")
4067 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4068 (match_operand:SI 2 "const_int_operand" "n")
4069 (match_operand:SI 3 "const_int_operand" "n")))]
4070 "arm_arch_thumb2
4071 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4072 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
4073 "sbfx%?\t%0, %1, %3, %2"
4074 [(set_attr "length" "4")
4075 (set_attr "predicable" "yes")
4076 (set_attr "type" "bfm")]
4077 )
4078
4079 (define_insn "extzv_t2"
4080 [(set (match_operand:SI 0 "s_register_operand" "=r")
4081 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4082 (match_operand:SI 2 "const_int_operand" "n")
4083 (match_operand:SI 3 "const_int_operand" "n")))]
4084 "arm_arch_thumb2
4085 && IN_RANGE (INTVAL (operands[3]), 0, 31)
4086 && IN_RANGE (INTVAL (operands[2]), 1, 32 - INTVAL (operands[3]))"
4087 "ubfx%?\t%0, %1, %3, %2"
4088 [(set_attr "length" "4")
4089 (set_attr "predicable" "yes")
4090 (set_attr "type" "bfm")]
4091 )
4092
4093
4094 ;; Division instructions
4095 (define_insn "divsi3"
4096 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4097 (div:SI (match_operand:SI 1 "s_register_operand" "r,r")
4098 (match_operand:SI 2 "s_register_operand" "r,r")))]
4099 "TARGET_IDIV"
4100 "@
4101 sdiv%?\t%0, %1, %2
4102 sdiv\t%0, %1, %2"
4103 [(set_attr "arch" "32,v8mb")
4104 (set_attr "predicable" "yes")
4105 (set_attr "type" "sdiv")]
4106 )
4107
4108 (define_insn "udivsi3"
4109 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4110 (udiv:SI (match_operand:SI 1 "s_register_operand" "r,r")
4111 (match_operand:SI 2 "s_register_operand" "r,r")))]
4112 "TARGET_IDIV"
4113 "@
4114 udiv%?\t%0, %1, %2
4115 udiv\t%0, %1, %2"
4116 [(set_attr "arch" "32,v8mb")
4117 (set_attr "predicable" "yes")
4118 (set_attr "type" "udiv")]
4119 )
4120
4121 \f
4122 ;; Unary arithmetic insns
4123
4124 (define_expand "negvsi3"
4125 [(match_operand:SI 0 "register_operand")
4126 (match_operand:SI 1 "register_operand")
4127 (match_operand 2 "")]
4128 "TARGET_32BIT"
4129 {
4130 emit_insn (gen_subsi3_compare (operands[0], const0_rtx, operands[1]));
4131 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4132
4133 DONE;
4134 })
4135
4136 (define_expand "negvdi3"
4137 [(match_operand:DI 0 "register_operand")
4138 (match_operand:DI 1 "register_operand")
4139 (match_operand 2 "")]
4140 "TARGET_ARM"
4141 {
4142 emit_insn (gen_negdi2_compare (operands[0], operands[1]));
4143 arm_gen_unlikely_cbranch (NE, CC_Vmode, operands[2]);
4144
4145 DONE;
4146 })
4147
4148
4149 (define_insn_and_split "negdi2_compare"
4150 [(set (reg:CC CC_REGNUM)
4151 (compare:CC
4152 (const_int 0)
4153 (match_operand:DI 1 "register_operand" "0,r")))
4154 (set (match_operand:DI 0 "register_operand" "=r,&r")
4155 (minus:DI (const_int 0) (match_dup 1)))]
4156 "TARGET_ARM"
4157 "#"
4158 "&& reload_completed"
4159 [(parallel [(set (reg:CC CC_REGNUM)
4160 (compare:CC (const_int 0) (match_dup 1)))
4161 (set (match_dup 0) (minus:SI (const_int 0)
4162 (match_dup 1)))])
4163 (parallel [(set (reg:CC CC_REGNUM)
4164 (compare:CC (const_int 0) (match_dup 3)))
4165 (set (match_dup 2)
4166 (minus:SI
4167 (minus:SI (const_int 0) (match_dup 3))
4168 (ltu:SI (reg:CC CC_REGNUM)
4169 (const_int 0))))])]
4170 {
4171 operands[2] = gen_highpart (SImode, operands[0]);
4172 operands[0] = gen_lowpart (SImode, operands[0]);
4173 operands[3] = gen_highpart (SImode, operands[1]);
4174 operands[1] = gen_lowpart (SImode, operands[1]);
4175 }
4176 [(set_attr "conds" "set")
4177 (set_attr "length" "8")
4178 (set_attr "type" "multiple")]
4179 )
4180
4181 (define_expand "negdi2"
4182 [(parallel
4183 [(set (match_operand:DI 0 "s_register_operand")
4184 (neg:DI (match_operand:DI 1 "s_register_operand")))
4185 (clobber (reg:CC CC_REGNUM))])]
4186 "TARGET_EITHER"
4187 )
4188
4189 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
4190 ;; The first alternative allows the common case of a *full* overlap.
4191 (define_insn_and_split "*negdi2_insn"
4192 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4193 (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
4194 (clobber (reg:CC CC_REGNUM))]
4195 "TARGET_32BIT"
4196 "#" ; rsbs %Q0, %Q1, #0; rsc %R0, %R1, #0 (ARM)
4197 ; negs %Q0, %Q1 ; sbc %R0, %R1, %R1, lsl #1 (Thumb-2)
4198 "TARGET_32BIT"
4199 [(parallel [(set (reg:CC CC_REGNUM)
4200 (compare:CC (const_int 0) (match_dup 1)))
4201 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4202 (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4203 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
4204 {
4205 operands[2] = gen_highpart (SImode, operands[0]);
4206 operands[0] = gen_lowpart (SImode, operands[0]);
4207 operands[3] = gen_highpart (SImode, operands[1]);
4208 operands[1] = gen_lowpart (SImode, operands[1]);
4209 }
4210 [(set_attr "conds" "clob")
4211 (set_attr "length" "8")
4212 (set_attr "type" "multiple")]
4213 )
4214
4215 (define_insn "*negsi2_carryin_compare"
4216 [(set (reg:CC CC_REGNUM)
4217 (compare:CC (const_int 0)
4218 (match_operand:SI 1 "s_register_operand" "r")))
4219 (set (match_operand:SI 0 "s_register_operand" "=r")
4220 (minus:SI (minus:SI (const_int 0)
4221 (match_dup 1))
4222 (match_operand:SI 2 "arm_borrow_operation" "")))]
4223 "TARGET_ARM"
4224 "rscs\\t%0, %1, #0"
4225 [(set_attr "conds" "set")
4226 (set_attr "type" "alus_imm")]
4227 )
4228
4229 (define_expand "negsi2"
4230 [(set (match_operand:SI 0 "s_register_operand")
4231 (neg:SI (match_operand:SI 1 "s_register_operand")))]
4232 "TARGET_EITHER"
4233 ""
4234 )
4235
4236 (define_insn "*arm_negsi2"
4237 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4238 (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
4239 "TARGET_32BIT"
4240 "rsb%?\\t%0, %1, #0"
4241 [(set_attr "predicable" "yes")
4242 (set_attr "predicable_short_it" "yes,no")
4243 (set_attr "arch" "t2,*")
4244 (set_attr "length" "4")
4245 (set_attr "type" "alu_sreg")]
4246 )
4247
4248 (define_expand "negsf2"
4249 [(set (match_operand:SF 0 "s_register_operand")
4250 (neg:SF (match_operand:SF 1 "s_register_operand")))]
4251 "TARGET_32BIT && TARGET_HARD_FLOAT"
4252 ""
4253 )
4254
4255 (define_expand "negdf2"
4256 [(set (match_operand:DF 0 "s_register_operand")
4257 (neg:DF (match_operand:DF 1 "s_register_operand")))]
4258 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
4259 "")
4260
4261 (define_insn_and_split "*zextendsidi_negsi"
4262 [(set (match_operand:DI 0 "s_register_operand" "=r")
4263 (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4264 "TARGET_32BIT"
4265 "#"
4266 ""
4267 [(set (match_dup 2)
4268 (neg:SI (match_dup 1)))
4269 (set (match_dup 3)
4270 (const_int 0))]
4271 {
4272 operands[2] = gen_lowpart (SImode, operands[0]);
4273 operands[3] = gen_highpart (SImode, operands[0]);
4274 }
4275 [(set_attr "length" "8")
4276 (set_attr "type" "multiple")]
4277 )
4278
4279 ;; Negate an extended 32-bit value.
4280 (define_insn_and_split "*negdi_extendsidi"
4281 [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4282 (neg:DI (sign_extend:DI
4283 (match_operand:SI 1 "s_register_operand" "l,r"))))
4284 (clobber (reg:CC CC_REGNUM))]
4285 "TARGET_32BIT"
4286 "#"
4287 "&& reload_completed"
4288 [(const_int 0)]
4289 {
4290 rtx low = gen_lowpart (SImode, operands[0]);
4291 rtx high = gen_highpart (SImode, operands[0]);
4292
4293 if (reg_overlap_mentioned_p (low, operands[1]))
4294 {
4295 /* Input overlaps the low word of the output. Use:
4296 asr Rhi, Rin, #31
4297 rsbs Rlo, Rin, #0
4298 rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4299 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
4300
4301 emit_insn (gen_rtx_SET (high,
4302 gen_rtx_ASHIFTRT (SImode, operands[1],
4303 GEN_INT (31))));
4304
4305 emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4306 if (TARGET_ARM)
4307 emit_insn (gen_rtx_SET (high,
4308 gen_rtx_MINUS (SImode,
4309 gen_rtx_MINUS (SImode,
4310 const0_rtx,
4311 high),
4312 gen_rtx_LTU (SImode,
4313 cc_reg,
4314 const0_rtx))));
4315 else
4316 {
4317 rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
4318 emit_insn (gen_rtx_SET (high,
4319 gen_rtx_MINUS (SImode,
4320 gen_rtx_MINUS (SImode,
4321 high,
4322 two_x),
4323 gen_rtx_LTU (SImode,
4324 cc_reg,
4325 const0_rtx))));
4326 }
4327 }
4328 else
4329 {
4330 /* No overlap, or overlap on high word. Use:
4331 rsb Rlo, Rin, #0
4332 bic Rhi, Rlo, Rin
4333 asr Rhi, Rhi, #31
4334 Flags not needed for this sequence. */
4335 emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
4336 emit_insn (gen_rtx_SET (high,
4337 gen_rtx_AND (SImode,
4338 gen_rtx_NOT (SImode, operands[1]),
4339 low)));
4340 emit_insn (gen_rtx_SET (high,
4341 gen_rtx_ASHIFTRT (SImode, high,
4342 GEN_INT (31))));
4343 }
4344 DONE;
4345 }
4346 [(set_attr "length" "12")
4347 (set_attr "arch" "t2,*")
4348 (set_attr "type" "multiple")]
4349 )
4350
4351 (define_insn_and_split "*negdi_zero_extendsidi"
4352 [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4353 (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4354 (clobber (reg:CC CC_REGNUM))]
4355 "TARGET_32BIT"
4356 "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4357 ;; Don't care what register is input to sbc,
4358 ;; since we just need to propagate the carry.
4359 "&& reload_completed"
4360 [(parallel [(set (reg:CC CC_REGNUM)
4361 (compare:CC (const_int 0) (match_dup 1)))
4362 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4363 (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4364 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))]
4365 {
4366 operands[2] = gen_highpart (SImode, operands[0]);
4367 operands[0] = gen_lowpart (SImode, operands[0]);
4368 }
4369 [(set_attr "conds" "clob")
4370 (set_attr "length" "8")
4371 (set_attr "type" "multiple")] ;; length in thumb is 4
4372 )
4373
4374 ;; abssi2 doesn't really clobber the condition codes if a different register
4375 ;; is being set. To keep things simple, assume during rtl manipulations that
4376 ;; it does, but tell the final scan operator the truth. Similarly for
4377 ;; (neg (abs...))
4378
4379 (define_expand "abssi2"
4380 [(parallel
4381 [(set (match_operand:SI 0 "s_register_operand")
4382 (abs:SI (match_operand:SI 1 "s_register_operand")))
4383 (clobber (match_dup 2))])]
4384 "TARGET_EITHER"
4385 "
4386 if (TARGET_THUMB1)
4387 operands[2] = gen_rtx_SCRATCH (SImode);
4388 else
4389 operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4390 ")
4391
4392 (define_insn_and_split "*arm_abssi2"
4393 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4394 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
4395 (clobber (reg:CC CC_REGNUM))]
4396 "TARGET_ARM"
4397 "#"
4398 "&& reload_completed"
4399 [(const_int 0)]
4400 {
4401 /* if (which_alternative == 0) */
4402 if (REGNO(operands[0]) == REGNO(operands[1]))
4403 {
4404 /* Emit the pattern:
4405 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4406 [(set (reg:CC CC_REGNUM)
4407 (compare:CC (match_dup 0) (const_int 0)))
4408 (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4409 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4410 */
4411 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4412 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4413 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4414 (gen_rtx_LT (SImode,
4415 gen_rtx_REG (CCmode, CC_REGNUM),
4416 const0_rtx)),
4417 (gen_rtx_SET (operands[0],
4418 (gen_rtx_MINUS (SImode,
4419 const0_rtx,
4420 operands[1]))))));
4421 DONE;
4422 }
4423 else
4424 {
4425 /* Emit the pattern:
4426 alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4427 [(set (match_dup 0)
4428 (xor:SI (match_dup 1)
4429 (ashiftrt:SI (match_dup 1) (const_int 31))))
4430 (set (match_dup 0)
4431 (minus:SI (match_dup 0)
4432 (ashiftrt:SI (match_dup 1) (const_int 31))))]
4433 */
4434 emit_insn (gen_rtx_SET (operands[0],
4435 gen_rtx_XOR (SImode,
4436 gen_rtx_ASHIFTRT (SImode,
4437 operands[1],
4438 GEN_INT (31)),
4439 operands[1])));
4440 emit_insn (gen_rtx_SET (operands[0],
4441 gen_rtx_MINUS (SImode,
4442 operands[0],
4443 gen_rtx_ASHIFTRT (SImode,
4444 operands[1],
4445 GEN_INT (31)))));
4446 DONE;
4447 }
4448 }
4449 [(set_attr "conds" "clob,*")
4450 (set_attr "shift" "1")
4451 (set_attr "predicable" "no, yes")
4452 (set_attr "length" "8")
4453 (set_attr "type" "multiple")]
4454 )
4455
4456 (define_insn_and_split "*arm_neg_abssi2"
4457 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4458 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
4459 (clobber (reg:CC CC_REGNUM))]
4460 "TARGET_ARM"
4461 "#"
4462 "&& reload_completed"
4463 [(const_int 0)]
4464 {
4465 /* if (which_alternative == 0) */
4466 if (REGNO (operands[0]) == REGNO (operands[1]))
4467 {
4468 /* Emit the pattern:
4469 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4470 */
4471 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
4472 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4473 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4474 gen_rtx_GT (SImode,
4475 gen_rtx_REG (CCmode, CC_REGNUM),
4476 const0_rtx),
4477 gen_rtx_SET (operands[0],
4478 (gen_rtx_MINUS (SImode,
4479 const0_rtx,
4480 operands[1])))));
4481 }
4482 else
4483 {
4484 /* Emit the pattern:
4485 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4486 */
4487 emit_insn (gen_rtx_SET (operands[0],
4488 gen_rtx_XOR (SImode,
4489 gen_rtx_ASHIFTRT (SImode,
4490 operands[1],
4491 GEN_INT (31)),
4492 operands[1])));
4493 emit_insn (gen_rtx_SET (operands[0],
4494 gen_rtx_MINUS (SImode,
4495 gen_rtx_ASHIFTRT (SImode,
4496 operands[1],
4497 GEN_INT (31)),
4498 operands[0])));
4499 }
4500 DONE;
4501 }
4502 [(set_attr "conds" "clob,*")
4503 (set_attr "shift" "1")
4504 (set_attr "predicable" "no, yes")
4505 (set_attr "length" "8")
4506 (set_attr "type" "multiple")]
4507 )
4508
4509 (define_expand "abssf2"
4510 [(set (match_operand:SF 0 "s_register_operand")
4511 (abs:SF (match_operand:SF 1 "s_register_operand")))]
4512 "TARGET_32BIT && TARGET_HARD_FLOAT"
4513 "")
4514
4515 (define_expand "absdf2"
4516 [(set (match_operand:DF 0 "s_register_operand")
4517 (abs:DF (match_operand:DF 1 "s_register_operand")))]
4518 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4519 "")
4520
4521 (define_expand "sqrtsf2"
4522 [(set (match_operand:SF 0 "s_register_operand")
4523 (sqrt:SF (match_operand:SF 1 "s_register_operand")))]
4524 "TARGET_32BIT && TARGET_HARD_FLOAT"
4525 "")
4526
4527 (define_expand "sqrtdf2"
4528 [(set (match_operand:DF 0 "s_register_operand")
4529 (sqrt:DF (match_operand:DF 1 "s_register_operand")))]
4530 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
4531 "")
4532
4533 (define_expand "one_cmplsi2"
4534 [(set (match_operand:SI 0 "s_register_operand")
4535 (not:SI (match_operand:SI 1 "s_register_operand")))]
4536 "TARGET_EITHER"
4537 ""
4538 )
4539
4540 (define_insn "*arm_one_cmplsi2"
4541 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4542 (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
4543 "TARGET_32BIT"
4544 "mvn%?\\t%0, %1"
4545 [(set_attr "predicable" "yes")
4546 (set_attr "predicable_short_it" "yes,no")
4547 (set_attr "arch" "t2,*")
4548 (set_attr "length" "4")
4549 (set_attr "type" "mvn_reg")]
4550 )
4551
4552 (define_insn "*notsi_compare0"
4553 [(set (reg:CC_NOOV CC_REGNUM)
4554 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4555 (const_int 0)))
4556 (set (match_operand:SI 0 "s_register_operand" "=r")
4557 (not:SI (match_dup 1)))]
4558 "TARGET_32BIT"
4559 "mvns%?\\t%0, %1"
4560 [(set_attr "conds" "set")
4561 (set_attr "type" "mvn_reg")]
4562 )
4563
4564 (define_insn "*notsi_compare0_scratch"
4565 [(set (reg:CC_NOOV CC_REGNUM)
4566 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4567 (const_int 0)))
4568 (clobber (match_scratch:SI 0 "=r"))]
4569 "TARGET_32BIT"
4570 "mvns%?\\t%0, %1"
4571 [(set_attr "conds" "set")
4572 (set_attr "type" "mvn_reg")]
4573 )
4574 \f
4575 ;; Fixed <--> Floating conversion insns
4576
4577 (define_expand "floatsihf2"
4578 [(set (match_operand:HF 0 "general_operand")
4579 (float:HF (match_operand:SI 1 "general_operand")))]
4580 "TARGET_EITHER"
4581 "
4582 {
4583 rtx op1 = gen_reg_rtx (SFmode);
4584 expand_float (op1, operands[1], 0);
4585 op1 = convert_to_mode (HFmode, op1, 0);
4586 emit_move_insn (operands[0], op1);
4587 DONE;
4588 }"
4589 )
4590
4591 (define_expand "floatdihf2"
4592 [(set (match_operand:HF 0 "general_operand")
4593 (float:HF (match_operand:DI 1 "general_operand")))]
4594 "TARGET_EITHER"
4595 "
4596 {
4597 rtx op1 = gen_reg_rtx (SFmode);
4598 expand_float (op1, operands[1], 0);
4599 op1 = convert_to_mode (HFmode, op1, 0);
4600 emit_move_insn (operands[0], op1);
4601 DONE;
4602 }"
4603 )
4604
4605 (define_expand "floatsisf2"
4606 [(set (match_operand:SF 0 "s_register_operand")
4607 (float:SF (match_operand:SI 1 "s_register_operand")))]
4608 "TARGET_32BIT && TARGET_HARD_FLOAT"
4609 "
4610 ")
4611
4612 (define_expand "floatsidf2"
4613 [(set (match_operand:DF 0 "s_register_operand")
4614 (float:DF (match_operand:SI 1 "s_register_operand")))]
4615 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4616 "
4617 ")
4618
4619 (define_expand "fix_trunchfsi2"
4620 [(set (match_operand:SI 0 "general_operand")
4621 (fix:SI (fix:HF (match_operand:HF 1 "general_operand"))))]
4622 "TARGET_EITHER"
4623 "
4624 {
4625 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4626 expand_fix (operands[0], op1, 0);
4627 DONE;
4628 }"
4629 )
4630
4631 (define_expand "fix_trunchfdi2"
4632 [(set (match_operand:DI 0 "general_operand")
4633 (fix:DI (fix:HF (match_operand:HF 1 "general_operand"))))]
4634 "TARGET_EITHER"
4635 "
4636 {
4637 rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4638 expand_fix (operands[0], op1, 0);
4639 DONE;
4640 }"
4641 )
4642
4643 (define_expand "fix_truncsfsi2"
4644 [(set (match_operand:SI 0 "s_register_operand")
4645 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"))))]
4646 "TARGET_32BIT && TARGET_HARD_FLOAT"
4647 "
4648 ")
4649
4650 (define_expand "fix_truncdfsi2"
4651 [(set (match_operand:SI 0 "s_register_operand")
4652 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"))))]
4653 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4654 "
4655 ")
4656
4657 ;; Truncation insns
4658
4659 (define_expand "truncdfsf2"
4660 [(set (match_operand:SF 0 "s_register_operand")
4661 (float_truncate:SF
4662 (match_operand:DF 1 "s_register_operand")))]
4663 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4664 ""
4665 )
4666
4667 ;; DFmode to HFmode conversions on targets without a single-step hardware
4668 ;; instruction for it would have to go through SFmode. This is dangerous
4669 ;; as it introduces double rounding.
4670 ;;
4671 ;; Disable this pattern unless we are in an unsafe math mode, or we have
4672 ;; a single-step instruction.
4673
4674 (define_expand "truncdfhf2"
4675 [(set (match_operand:HF 0 "s_register_operand")
4676 (float_truncate:HF
4677 (match_operand:DF 1 "s_register_operand")))]
4678 "(TARGET_EITHER && flag_unsafe_math_optimizations)
4679 || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
4680 {
4681 /* We don't have a direct instruction for this, so we must be in
4682 an unsafe math mode, and going via SFmode. */
4683
4684 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
4685 {
4686 rtx op1;
4687 op1 = convert_to_mode (SFmode, operands[1], 0);
4688 op1 = convert_to_mode (HFmode, op1, 0);
4689 emit_move_insn (operands[0], op1);
4690 DONE;
4691 }
4692 /* Otherwise, we will pick this up as a single instruction with
4693 no intermediary rounding. */
4694 }
4695 )
4696 \f
4697 ;; Zero and sign extension instructions.
4698
4699 (define_insn "zero_extend<mode>di2"
4700 [(set (match_operand:DI 0 "s_register_operand" "=r,?r")
4701 (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4702 "<qhs_zextenddi_cstr>")))]
4703 "TARGET_32BIT <qhs_zextenddi_cond>"
4704 "#"
4705 [(set_attr "length" "4,8")
4706 (set_attr "arch" "*,*")
4707 (set_attr "ce_count" "2")
4708 (set_attr "predicable" "yes")
4709 (set_attr "type" "mov_reg,multiple")]
4710 )
4711
4712 (define_insn "extend<mode>di2"
4713 [(set (match_operand:DI 0 "s_register_operand" "=r,?r,?r")
4714 (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4715 "<qhs_extenddi_cstr>")))]
4716 "TARGET_32BIT <qhs_sextenddi_cond>"
4717 "#"
4718 [(set_attr "length" "4,8,8")
4719 (set_attr "ce_count" "2")
4720 (set_attr "shift" "1")
4721 (set_attr "predicable" "yes")
4722 (set_attr "arch" "*,a,t")
4723 (set_attr "type" "mov_reg,multiple,multiple")]
4724 )
4725
4726 ;; Splits for all extensions to DImode
4727 (define_split
4728 [(set (match_operand:DI 0 "s_register_operand" "")
4729 (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4730 "TARGET_32BIT"
4731 [(set (match_dup 0) (match_dup 1))]
4732 {
4733 rtx lo_part = gen_lowpart (SImode, operands[0]);
4734 machine_mode src_mode = GET_MODE (operands[1]);
4735
4736 if (src_mode == SImode)
4737 emit_move_insn (lo_part, operands[1]);
4738 else
4739 emit_insn (gen_rtx_SET (lo_part,
4740 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4741 operands[0] = gen_highpart (SImode, operands[0]);
4742 operands[1] = const0_rtx;
4743 })
4744
4745 (define_split
4746 [(set (match_operand:DI 0 "s_register_operand" "")
4747 (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4748 "TARGET_32BIT"
4749 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4750 {
4751 rtx lo_part = gen_lowpart (SImode, operands[0]);
4752 machine_mode src_mode = GET_MODE (operands[1]);
4753
4754 if (src_mode == SImode)
4755 emit_move_insn (lo_part, operands[1]);
4756 else
4757 emit_insn (gen_rtx_SET (lo_part,
4758 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4759 operands[1] = lo_part;
4760 operands[0] = gen_highpart (SImode, operands[0]);
4761 })
4762
4763 (define_expand "zero_extendhisi2"
4764 [(set (match_operand:SI 0 "s_register_operand")
4765 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
4766 "TARGET_EITHER"
4767 {
4768 if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4769 {
4770 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4771 DONE;
4772 }
4773 if (!arm_arch6 && !MEM_P (operands[1]))
4774 {
4775 rtx t = gen_lowpart (SImode, operands[1]);
4776 rtx tmp = gen_reg_rtx (SImode);
4777 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4778 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4779 DONE;
4780 }
4781 })
4782
4783 (define_split
4784 [(set (match_operand:SI 0 "s_register_operand" "")
4785 (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
4786 "!TARGET_THUMB2 && !arm_arch6"
4787 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4788 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4789 {
4790 operands[2] = gen_lowpart (SImode, operands[1]);
4791 })
4792
4793 (define_insn "*arm_zero_extendhisi2"
4794 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4795 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4796 "TARGET_ARM && arm_arch4 && !arm_arch6"
4797 "@
4798 #
4799 ldrh%?\\t%0, %1"
4800 [(set_attr "type" "alu_shift_reg,load_byte")
4801 (set_attr "predicable" "yes")]
4802 )
4803
4804 (define_insn "*arm_zero_extendhisi2_v6"
4805 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4806 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
4807 "TARGET_ARM && arm_arch6"
4808 "@
4809 uxth%?\\t%0, %1
4810 ldrh%?\\t%0, %1"
4811 [(set_attr "predicable" "yes")
4812 (set_attr "type" "extend,load_byte")]
4813 )
4814
4815 (define_insn "*arm_zero_extendhisi2addsi"
4816 [(set (match_operand:SI 0 "s_register_operand" "=r")
4817 (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4818 (match_operand:SI 2 "s_register_operand" "r")))]
4819 "TARGET_INT_SIMD"
4820 "uxtah%?\\t%0, %2, %1"
4821 [(set_attr "type" "alu_shift_reg")
4822 (set_attr "predicable" "yes")]
4823 )
4824
4825 (define_expand "zero_extendqisi2"
4826 [(set (match_operand:SI 0 "s_register_operand")
4827 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
4828 "TARGET_EITHER"
4829 {
4830 if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
4831 {
4832 emit_insn (gen_andsi3 (operands[0],
4833 gen_lowpart (SImode, operands[1]),
4834 GEN_INT (255)));
4835 DONE;
4836 }
4837 if (!arm_arch6 && !MEM_P (operands[1]))
4838 {
4839 rtx t = gen_lowpart (SImode, operands[1]);
4840 rtx tmp = gen_reg_rtx (SImode);
4841 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4842 emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4843 DONE;
4844 }
4845 })
4846
4847 (define_split
4848 [(set (match_operand:SI 0 "s_register_operand" "")
4849 (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
4850 "!arm_arch6"
4851 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4852 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4853 {
4854 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4855 if (TARGET_ARM)
4856 {
4857 emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4858 DONE;
4859 }
4860 })
4861
4862 (define_insn "*arm_zero_extendqisi2"
4863 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4864 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4865 "TARGET_ARM && !arm_arch6"
4866 "@
4867 #
4868 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
4869 [(set_attr "length" "8,4")
4870 (set_attr "type" "alu_shift_reg,load_byte")
4871 (set_attr "predicable" "yes")]
4872 )
4873
4874 (define_insn "*arm_zero_extendqisi2_v6"
4875 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4876 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
4877 "TARGET_ARM && arm_arch6"
4878 "@
4879 uxtb%?\\t%0, %1
4880 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
4881 [(set_attr "type" "extend,load_byte")
4882 (set_attr "predicable" "yes")]
4883 )
4884
4885 (define_insn "*arm_zero_extendqisi2addsi"
4886 [(set (match_operand:SI 0 "s_register_operand" "=r")
4887 (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4888 (match_operand:SI 2 "s_register_operand" "r")))]
4889 "TARGET_INT_SIMD"
4890 "uxtab%?\\t%0, %2, %1"
4891 [(set_attr "predicable" "yes")
4892 (set_attr "type" "alu_shift_reg")]
4893 )
4894
4895 (define_split
4896 [(set (match_operand:SI 0 "s_register_operand" "")
4897 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4898 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4899 "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
4900 [(set (match_dup 2) (match_dup 1))
4901 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4902 ""
4903 )
4904
4905 (define_split
4906 [(set (match_operand:SI 0 "s_register_operand" "")
4907 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4908 (clobber (match_operand:SI 2 "s_register_operand" ""))]
4909 "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
4910 [(set (match_dup 2) (match_dup 1))
4911 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4912 ""
4913 )
4914
4915
4916 (define_split
4917 [(set (match_operand:SI 0 "s_register_operand" "")
4918 (IOR_XOR:SI (and:SI (ashift:SI
4919 (match_operand:SI 1 "s_register_operand" "")
4920 (match_operand:SI 2 "const_int_operand" ""))
4921 (match_operand:SI 3 "const_int_operand" ""))
4922 (zero_extend:SI
4923 (match_operator 5 "subreg_lowpart_operator"
4924 [(match_operand:SI 4 "s_register_operand" "")]))))]
4925 "TARGET_32BIT
4926 && (UINTVAL (operands[3])
4927 == (GET_MODE_MASK (GET_MODE (operands[5]))
4928 & (GET_MODE_MASK (GET_MODE (operands[5]))
4929 << (INTVAL (operands[2])))))"
4930 [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
4931 (match_dup 4)))
4932 (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4933 "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4934 )
4935
4936 (define_insn "*compareqi_eq0"
4937 [(set (reg:CC_Z CC_REGNUM)
4938 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4939 (const_int 0)))]
4940 "TARGET_32BIT"
4941 "tst%?\\t%0, #255"
4942 [(set_attr "conds" "set")
4943 (set_attr "predicable" "yes")
4944 (set_attr "type" "logic_imm")]
4945 )
4946
4947 (define_expand "extendhisi2"
4948 [(set (match_operand:SI 0 "s_register_operand")
4949 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
4950 "TARGET_EITHER"
4951 {
4952 if (TARGET_THUMB1)
4953 {
4954 emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4955 DONE;
4956 }
4957 if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4958 {
4959 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4960 DONE;
4961 }
4962
4963 if (!arm_arch6 && !MEM_P (operands[1]))
4964 {
4965 rtx t = gen_lowpart (SImode, operands[1]);
4966 rtx tmp = gen_reg_rtx (SImode);
4967 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4968 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4969 DONE;
4970 }
4971 })
4972
4973 (define_split
4974 [(parallel
4975 [(set (match_operand:SI 0 "register_operand" "")
4976 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4977 (clobber (match_scratch:SI 2 ""))])]
4978 "!arm_arch6"
4979 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4980 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4981 {
4982 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4983 })
4984
4985 ;; This pattern will only be used when ldsh is not available
4986 (define_expand "extendhisi2_mem"
4987 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4988 (set (match_dup 3)
4989 (zero_extend:SI (match_dup 7)))
4990 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4991 (set (match_operand:SI 0 "" "")
4992 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4993 "TARGET_ARM"
4994 "
4995 {
4996 rtx mem1, mem2;
4997 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4998
4999 mem1 = change_address (operands[1], QImode, addr);
5000 mem2 = change_address (operands[1], QImode,
5001 plus_constant (Pmode, addr, 1));
5002 operands[0] = gen_lowpart (SImode, operands[0]);
5003 operands[1] = mem1;
5004 operands[2] = gen_reg_rtx (SImode);
5005 operands[3] = gen_reg_rtx (SImode);
5006 operands[6] = gen_reg_rtx (SImode);
5007 operands[7] = mem2;
5008
5009 if (BYTES_BIG_ENDIAN)
5010 {
5011 operands[4] = operands[2];
5012 operands[5] = operands[3];
5013 }
5014 else
5015 {
5016 operands[4] = operands[3];
5017 operands[5] = operands[2];
5018 }
5019 }"
5020 )
5021
5022 (define_split
5023 [(set (match_operand:SI 0 "register_operand" "")
5024 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5025 "!arm_arch6"
5026 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5027 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5028 {
5029 operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5030 })
5031
5032 (define_insn "*arm_extendhisi2"
5033 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5034 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
5035 "TARGET_ARM && arm_arch4 && !arm_arch6"
5036 "@
5037 #
5038 ldrsh%?\\t%0, %1"
5039 [(set_attr "length" "8,4")
5040 (set_attr "type" "alu_shift_reg,load_byte")
5041 (set_attr "predicable" "yes")]
5042 )
5043
5044 ;; ??? Check Thumb-2 pool range
5045 (define_insn "*arm_extendhisi2_v6"
5046 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5047 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
5048 "TARGET_32BIT && arm_arch6"
5049 "@
5050 sxth%?\\t%0, %1
5051 ldrsh%?\\t%0, %1"
5052 [(set_attr "type" "extend,load_byte")
5053 (set_attr "predicable" "yes")]
5054 )
5055
5056 (define_insn "*arm_extendhisi2addsi"
5057 [(set (match_operand:SI 0 "s_register_operand" "=r")
5058 (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5059 (match_operand:SI 2 "s_register_operand" "r")))]
5060 "TARGET_INT_SIMD"
5061 "sxtah%?\\t%0, %2, %1"
5062 [(set_attr "type" "alu_shift_reg")]
5063 )
5064
5065 (define_expand "extendqihi2"
5066 [(set (match_dup 2)
5067 (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")
5068 (const_int 24)))
5069 (set (match_operand:HI 0 "s_register_operand")
5070 (ashiftrt:SI (match_dup 2)
5071 (const_int 24)))]
5072 "TARGET_ARM"
5073 "
5074 {
5075 if (arm_arch4 && MEM_P (operands[1]))
5076 {
5077 emit_insn (gen_rtx_SET (operands[0],
5078 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5079 DONE;
5080 }
5081 if (!s_register_operand (operands[1], QImode))
5082 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5083 operands[0] = gen_lowpart (SImode, operands[0]);
5084 operands[1] = gen_lowpart (SImode, operands[1]);
5085 operands[2] = gen_reg_rtx (SImode);
5086 }"
5087 )
5088
5089 (define_insn "*arm_extendqihi_insn"
5090 [(set (match_operand:HI 0 "s_register_operand" "=r")
5091 (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
5092 "TARGET_ARM && arm_arch4"
5093 "ldrsb%?\\t%0, %1"
5094 [(set_attr "type" "load_byte")
5095 (set_attr "predicable" "yes")]
5096 )
5097
5098 (define_expand "extendqisi2"
5099 [(set (match_operand:SI 0 "s_register_operand")
5100 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")))]
5101 "TARGET_EITHER"
5102 {
5103 if (!arm_arch4 && MEM_P (operands[1]))
5104 operands[1] = copy_to_mode_reg (QImode, operands[1]);
5105
5106 if (!arm_arch6 && !MEM_P (operands[1]))
5107 {
5108 rtx t = gen_lowpart (SImode, operands[1]);
5109 rtx tmp = gen_reg_rtx (SImode);
5110 emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5111 emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5112 DONE;
5113 }
5114 })
5115
5116 (define_split
5117 [(set (match_operand:SI 0 "register_operand" "")
5118 (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5119 "!arm_arch6"
5120 [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5121 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5122 {
5123 operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5124 })
5125
5126 (define_insn "*arm_extendqisi"
5127 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5128 (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5129 "TARGET_ARM && arm_arch4 && !arm_arch6"
5130 "@
5131 #
5132 ldrsb%?\\t%0, %1"
5133 [(set_attr "length" "8,4")
5134 (set_attr "type" "alu_shift_reg,load_byte")
5135 (set_attr "predicable" "yes")]
5136 )
5137
5138 (define_insn "*arm_extendqisi_v6"
5139 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5140 (sign_extend:SI
5141 (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5142 "TARGET_ARM && arm_arch6"
5143 "@
5144 sxtb%?\\t%0, %1
5145 ldrsb%?\\t%0, %1"
5146 [(set_attr "type" "extend,load_byte")
5147 (set_attr "predicable" "yes")]
5148 )
5149
5150 (define_insn "*arm_extendqisi2addsi"
5151 [(set (match_operand:SI 0 "s_register_operand" "=r")
5152 (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5153 (match_operand:SI 2 "s_register_operand" "r")))]
5154 "TARGET_INT_SIMD"
5155 "sxtab%?\\t%0, %2, %1"
5156 [(set_attr "type" "alu_shift_reg")
5157 (set_attr "predicable" "yes")]
5158 )
5159
5160 (define_expand "extendsfdf2"
5161 [(set (match_operand:DF 0 "s_register_operand")
5162 (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
5163 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5164 ""
5165 )
5166
5167 ;; HFmode -> DFmode conversions where we don't have an instruction for it
5168 ;; must go through SFmode.
5169 ;;
5170 ;; This is always safe for an extend.
5171
5172 (define_expand "extendhfdf2"
5173 [(set (match_operand:DF 0 "s_register_operand")
5174 (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
5175 "TARGET_EITHER"
5176 {
5177 /* We don't have a direct instruction for this, so go via SFmode. */
5178 if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
5179 {
5180 rtx op1;
5181 op1 = convert_to_mode (SFmode, operands[1], 0);
5182 op1 = convert_to_mode (DFmode, op1, 0);
5183 emit_insn (gen_movdf (operands[0], op1));
5184 DONE;
5185 }
5186 /* Otherwise, we're done producing RTL and will pick up the correct
5187 pattern to do this with one rounding-step in a single instruction. */
5188 }
5189 )
5190 \f
5191 ;; Move insns (including loads and stores)
5192
5193 ;; XXX Just some ideas about movti.
5194 ;; I don't think these are a good idea on the arm, there just aren't enough
5195 ;; registers
5196 ;;(define_expand "loadti"
5197 ;; [(set (match_operand:TI 0 "s_register_operand")
5198 ;; (mem:TI (match_operand:SI 1 "address_operand")))]
5199 ;; "" "")
5200
5201 ;;(define_expand "storeti"
5202 ;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
5203 ;; (match_operand:TI 1 "s_register_operand"))]
5204 ;; "" "")
5205
5206 ;;(define_expand "movti"
5207 ;; [(set (match_operand:TI 0 "general_operand")
5208 ;; (match_operand:TI 1 "general_operand"))]
5209 ;; ""
5210 ;; "
5211 ;;{
5212 ;; rtx insn;
5213 ;;
5214 ;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
5215 ;; operands[1] = copy_to_reg (operands[1]);
5216 ;; if (MEM_P (operands[0]))
5217 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5218 ;; else if (MEM_P (operands[1]))
5219 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5220 ;; else
5221 ;; FAIL;
5222 ;;
5223 ;; emit_insn (insn);
5224 ;; DONE;
5225 ;;}")
5226
5227 ;; Recognize garbage generated above.
5228
5229 ;;(define_insn ""
5230 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5231 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5232 ;; ""
5233 ;; "*
5234 ;; {
5235 ;; register mem = (which_alternative < 3);
5236 ;; register const char *template;
5237 ;;
5238 ;; operands[mem] = XEXP (operands[mem], 0);
5239 ;; switch (which_alternative)
5240 ;; {
5241 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5242 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5243 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5244 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5245 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5246 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
5247 ;; }
5248 ;; output_asm_insn (template, operands);
5249 ;; return \"\";
5250 ;; }")
5251
5252 (define_expand "movdi"
5253 [(set (match_operand:DI 0 "general_operand")
5254 (match_operand:DI 1 "general_operand"))]
5255 "TARGET_EITHER"
5256 "
5257 gcc_checking_assert (aligned_operand (operands[0], DImode));
5258 gcc_checking_assert (aligned_operand (operands[1], DImode));
5259 if (can_create_pseudo_p ())
5260 {
5261 if (!REG_P (operands[0]))
5262 operands[1] = force_reg (DImode, operands[1]);
5263 }
5264 if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
5265 && !targetm.hard_regno_mode_ok (REGNO (operands[0]), DImode))
5266 {
5267 /* Avoid LDRD's into an odd-numbered register pair in ARM state
5268 when expanding function calls. */
5269 gcc_assert (can_create_pseudo_p ());
5270 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5271 {
5272 /* Perform load into legal reg pair first, then move. */
5273 rtx reg = gen_reg_rtx (DImode);
5274 emit_insn (gen_movdi (reg, operands[1]));
5275 operands[1] = reg;
5276 }
5277 emit_move_insn (gen_lowpart (SImode, operands[0]),
5278 gen_lowpart (SImode, operands[1]));
5279 emit_move_insn (gen_highpart (SImode, operands[0]),
5280 gen_highpart (SImode, operands[1]));
5281 DONE;
5282 }
5283 else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
5284 && !targetm.hard_regno_mode_ok (REGNO (operands[1]), DImode))
5285 {
5286 /* Avoid STRD's from an odd-numbered register pair in ARM state
5287 when expanding function prologue. */
5288 gcc_assert (can_create_pseudo_p ());
5289 rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5290 ? gen_reg_rtx (DImode)
5291 : operands[0];
5292 emit_move_insn (gen_lowpart (SImode, split_dest),
5293 gen_lowpart (SImode, operands[1]));
5294 emit_move_insn (gen_highpart (SImode, split_dest),
5295 gen_highpart (SImode, operands[1]));
5296 if (split_dest != operands[0])
5297 emit_insn (gen_movdi (operands[0], split_dest));
5298 DONE;
5299 }
5300 "
5301 )
5302
5303 (define_insn "*arm_movdi"
5304 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5305 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
5306 "TARGET_32BIT
5307 && !(TARGET_HARD_FLOAT)
5308 && !TARGET_IWMMXT
5309 && ( register_operand (operands[0], DImode)
5310 || register_operand (operands[1], DImode))"
5311 "*
5312 switch (which_alternative)
5313 {
5314 case 0:
5315 case 1:
5316 case 2:
5317 return \"#\";
5318 case 3:
5319 /* Cannot load it directly, split to load it via MOV / MOVT. */
5320 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
5321 return \"#\";
5322 /* Fall through. */
5323 default:
5324 return output_move_double (operands, true, NULL);
5325 }
5326 "
5327 [(set_attr "length" "8,12,16,8,8")
5328 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
5329 (set_attr "arm_pool_range" "*,*,*,1020,*")
5330 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5331 (set_attr "thumb2_pool_range" "*,*,*,4094,*")
5332 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5333 )
5334
5335 (define_split
5336 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5337 (match_operand:ANY64 1 "immediate_operand" ""))]
5338 "TARGET_32BIT
5339 && reload_completed
5340 && (arm_disable_literal_pool
5341 || (arm_const_double_inline_cost (operands[1])
5342 <= arm_max_const_double_inline_cost ()))"
5343 [(const_int 0)]
5344 "
5345 arm_split_constant (SET, SImode, curr_insn,
5346 INTVAL (gen_lowpart (SImode, operands[1])),
5347 gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5348 arm_split_constant (SET, SImode, curr_insn,
5349 INTVAL (gen_highpart_mode (SImode,
5350 GET_MODE (operands[0]),
5351 operands[1])),
5352 gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5353 DONE;
5354 "
5355 )
5356
5357 ; If optimizing for size, or if we have load delay slots, then
5358 ; we want to split the constant into two separate operations.
5359 ; In both cases this may split a trivial part into a single data op
5360 ; leaving a single complex constant to load. We can also get longer
5361 ; offsets in a LDR which means we get better chances of sharing the pool
5362 ; entries. Finally, we can normally do a better job of scheduling
5363 ; LDR instructions than we can with LDM.
5364 ; This pattern will only match if the one above did not.
5365 (define_split
5366 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5367 (match_operand:ANY64 1 "const_double_operand" ""))]
5368 "TARGET_ARM && reload_completed
5369 && arm_const_double_by_parts (operands[1])"
5370 [(set (match_dup 0) (match_dup 1))
5371 (set (match_dup 2) (match_dup 3))]
5372 "
5373 operands[2] = gen_highpart (SImode, operands[0]);
5374 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5375 operands[1]);
5376 operands[0] = gen_lowpart (SImode, operands[0]);
5377 operands[1] = gen_lowpart (SImode, operands[1]);
5378 "
5379 )
5380
5381 (define_split
5382 [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5383 (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5384 "TARGET_EITHER && reload_completed"
5385 [(set (match_dup 0) (match_dup 1))
5386 (set (match_dup 2) (match_dup 3))]
5387 "
5388 operands[2] = gen_highpart (SImode, operands[0]);
5389 operands[3] = gen_highpart (SImode, operands[1]);
5390 operands[0] = gen_lowpart (SImode, operands[0]);
5391 operands[1] = gen_lowpart (SImode, operands[1]);
5392
5393 /* Handle a partial overlap. */
5394 if (rtx_equal_p (operands[0], operands[3]))
5395 {
5396 rtx tmp0 = operands[0];
5397 rtx tmp1 = operands[1];
5398
5399 operands[0] = operands[2];
5400 operands[1] = operands[3];
5401 operands[2] = tmp0;
5402 operands[3] = tmp1;
5403 }
5404 "
5405 )
5406
5407 ;; We can't actually do base+index doubleword loads if the index and
5408 ;; destination overlap. Split here so that we at least have chance to
5409 ;; schedule.
5410 (define_split
5411 [(set (match_operand:DI 0 "s_register_operand" "")
5412 (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5413 (match_operand:SI 2 "s_register_operand" ""))))]
5414 "TARGET_LDRD
5415 && reg_overlap_mentioned_p (operands[0], operands[1])
5416 && reg_overlap_mentioned_p (operands[0], operands[2])"
5417 [(set (match_dup 4)
5418 (plus:SI (match_dup 1)
5419 (match_dup 2)))
5420 (set (match_dup 0)
5421 (mem:DI (match_dup 4)))]
5422 "
5423 operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5424 "
5425 )
5426
5427 (define_expand "movsi"
5428 [(set (match_operand:SI 0 "general_operand")
5429 (match_operand:SI 1 "general_operand"))]
5430 "TARGET_EITHER"
5431 "
5432 {
5433 rtx base, offset, tmp;
5434
5435 gcc_checking_assert (aligned_operand (operands[0], SImode));
5436 gcc_checking_assert (aligned_operand (operands[1], SImode));
5437 if (TARGET_32BIT || TARGET_HAVE_MOVT)
5438 {
5439 /* Everything except mem = const or mem = mem can be done easily. */
5440 if (MEM_P (operands[0]))
5441 operands[1] = force_reg (SImode, operands[1]);
5442 if (arm_general_register_operand (operands[0], SImode)
5443 && CONST_INT_P (operands[1])
5444 && !(const_ok_for_arm (INTVAL (operands[1]))
5445 || const_ok_for_arm (~INTVAL (operands[1]))))
5446 {
5447 if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
5448 {
5449 emit_insn (gen_rtx_SET (operands[0], operands[1]));
5450 DONE;
5451 }
5452 else
5453 {
5454 arm_split_constant (SET, SImode, NULL_RTX,
5455 INTVAL (operands[1]), operands[0], NULL_RTX,
5456 optimize && can_create_pseudo_p ());
5457 DONE;
5458 }
5459 }
5460 }
5461 else /* Target doesn't have MOVT... */
5462 {
5463 if (can_create_pseudo_p ())
5464 {
5465 if (!REG_P (operands[0]))
5466 operands[1] = force_reg (SImode, operands[1]);
5467 }
5468 }
5469
5470 split_const (operands[1], &base, &offset);
5471 if (INTVAL (offset) != 0
5472 && targetm.cannot_force_const_mem (SImode, operands[1]))
5473 {
5474 tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5475 emit_move_insn (tmp, base);
5476 emit_insn (gen_addsi3 (operands[0], tmp, offset));
5477 DONE;
5478 }
5479
5480 tmp = can_create_pseudo_p () ? NULL_RTX : operands[0];
5481
5482 /* Recognize the case where operand[1] is a reference to thread-local
5483 data and load its address to a register. Offsets have been split off
5484 already. */
5485 if (arm_tls_referenced_p (operands[1]))
5486 operands[1] = legitimize_tls_address (operands[1], tmp);
5487 else if (flag_pic
5488 && (CONSTANT_P (operands[1])
5489 || symbol_mentioned_p (operands[1])
5490 || label_mentioned_p (operands[1])))
5491 operands[1] =
5492 legitimize_pic_address (operands[1], SImode, tmp, NULL_RTX, false);
5493 }
5494 "
5495 )
5496
5497 ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5498 ;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5499 ;; so this does not matter.
5500 (define_insn "*arm_movt"
5501 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
5502 (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
5503 (match_operand:SI 2 "general_operand" "i,i")))]
5504 "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
5505 "@
5506 movt%?\t%0, #:upper16:%c2
5507 movt\t%0, #:upper16:%c2"
5508 [(set_attr "arch" "32,v8mb")
5509 (set_attr "predicable" "yes")
5510 (set_attr "length" "4")
5511 (set_attr "type" "alu_sreg")]
5512 )
5513
5514 (define_insn "*arm_movsi_insn"
5515 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5516 (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
5517 "TARGET_ARM && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
5518 && ( register_operand (operands[0], SImode)
5519 || register_operand (operands[1], SImode))"
5520 "@
5521 mov%?\\t%0, %1
5522 mov%?\\t%0, %1
5523 mvn%?\\t%0, #%B1
5524 movw%?\\t%0, %1
5525 ldr%?\\t%0, %1
5526 str%?\\t%1, %0"
5527 [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load_4,store_4")
5528 (set_attr "predicable" "yes")
5529 (set_attr "arch" "*,*,*,v6t2,*,*")
5530 (set_attr "pool_range" "*,*,*,*,4096,*")
5531 (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5532 )
5533
5534 (define_split
5535 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5536 (match_operand:SI 1 "const_int_operand" ""))]
5537 "(TARGET_32BIT || TARGET_HAVE_MOVT)
5538 && (!(const_ok_for_arm (INTVAL (operands[1]))
5539 || const_ok_for_arm (~INTVAL (operands[1]))))"
5540 [(clobber (const_int 0))]
5541 "
5542 arm_split_constant (SET, SImode, NULL_RTX,
5543 INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5544 DONE;
5545 "
5546 )
5547
5548 ;; A normal way to do (symbol + offset) requires three instructions at least
5549 ;; (depends on how big the offset is) as below:
5550 ;; movw r0, #:lower16:g
5551 ;; movw r0, #:upper16:g
5552 ;; adds r0, #4
5553 ;;
5554 ;; A better way would be:
5555 ;; movw r0, #:lower16:g+4
5556 ;; movw r0, #:upper16:g+4
5557 ;;
5558 ;; The limitation of this way is that the length of offset should be a 16-bit
5559 ;; signed value, because current assembler only supports REL type relocation for
5560 ;; such case. If the more powerful RELA type is supported in future, we should
5561 ;; update this pattern to go with better way.
5562 (define_split
5563 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5564 (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5565 (match_operand:SI 2 "const_int_operand" ""))))]
5566 "TARGET_THUMB
5567 && TARGET_HAVE_MOVT
5568 && arm_disable_literal_pool
5569 && reload_completed
5570 && GET_CODE (operands[1]) == SYMBOL_REF"
5571 [(clobber (const_int 0))]
5572 "
5573 int offset = INTVAL (operands[2]);
5574
5575 if (offset < -0x8000 || offset > 0x7fff)
5576 {
5577 arm_emit_movpair (operands[0], operands[1]);
5578 emit_insn (gen_rtx_SET (operands[0],
5579 gen_rtx_PLUS (SImode, operands[0], operands[2])));
5580 }
5581 else
5582 {
5583 rtx op = gen_rtx_CONST (SImode,
5584 gen_rtx_PLUS (SImode, operands[1], operands[2]));
5585 arm_emit_movpair (operands[0], op);
5586 }
5587 "
5588 )
5589
5590 ;; Split symbol_refs at the later stage (after cprop), instead of generating
5591 ;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5592 ;; and lo_sum would be merged back into memory load at cprop. However,
5593 ;; if the default is to prefer movt/movw rather than a load from the constant
5594 ;; pool, the performance is better.
5595 (define_split
5596 [(set (match_operand:SI 0 "arm_general_register_operand" "")
5597 (match_operand:SI 1 "general_operand" ""))]
5598 "TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5599 && !target_word_relocations
5600 && !arm_tls_referenced_p (operands[1])"
5601 [(clobber (const_int 0))]
5602 {
5603 arm_emit_movpair (operands[0], operands[1]);
5604 DONE;
5605 })
5606
5607 ;; When generating pic, we need to load the symbol offset into a register.
5608 ;; So that the optimizer does not confuse this with a normal symbol load
5609 ;; we use an unspec. The offset will be loaded from a constant pool entry,
5610 ;; since that is the only type of relocation we can use.
5611
5612 ;; Wrap calculation of the whole PIC address in a single pattern for the
5613 ;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5614 ;; a PIC address involves two loads from memory, so we want to CSE it
5615 ;; as often as possible.
5616 ;; This pattern will be split into one of the pic_load_addr_* patterns
5617 ;; and a move after GCSE optimizations.
5618 ;;
5619 ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5620 (define_expand "calculate_pic_address"
5621 [(set (match_operand:SI 0 "register_operand")
5622 (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
5623 (unspec:SI [(match_operand:SI 2 "" "")]
5624 UNSPEC_PIC_SYM))))]
5625 "flag_pic"
5626 )
5627
5628 ;; Split calculate_pic_address into pic_load_addr_* and a move.
5629 (define_split
5630 [(set (match_operand:SI 0 "register_operand" "")
5631 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5632 (unspec:SI [(match_operand:SI 2 "" "")]
5633 UNSPEC_PIC_SYM))))]
5634 "flag_pic"
5635 [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5636 (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5637 "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5638 )
5639
5640 ;; operand1 is the memory address to go into
5641 ;; pic_load_addr_32bit.
5642 ;; operand2 is the PIC label to be emitted
5643 ;; from pic_add_dot_plus_eight.
5644 ;; We do this to allow hoisting of the entire insn.
5645 (define_insn_and_split "pic_load_addr_unified"
5646 [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5647 (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5648 (match_operand:SI 2 "" "")]
5649 UNSPEC_PIC_UNIFIED))]
5650 "flag_pic"
5651 "#"
5652 "&& reload_completed"
5653 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5654 (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5655 (match_dup 2)] UNSPEC_PIC_BASE))]
5656 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5657 [(set_attr "type" "load_4,load_4,load_4")
5658 (set_attr "pool_range" "4096,4094,1022")
5659 (set_attr "neg_pool_range" "4084,0,0")
5660 (set_attr "arch" "a,t2,t1")
5661 (set_attr "length" "8,6,4")]
5662 )
5663
5664 ;; The rather odd constraints on the following are to force reload to leave
5665 ;; the insn alone, and to force the minipool generation pass to then move
5666 ;; the GOT symbol to memory.
5667
5668 (define_insn "pic_load_addr_32bit"
5669 [(set (match_operand:SI 0 "s_register_operand" "=r")
5670 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5671 "TARGET_32BIT && flag_pic"
5672 "ldr%?\\t%0, %1"
5673 [(set_attr "type" "load_4")
5674 (set (attr "pool_range")
5675 (if_then_else (eq_attr "is_thumb" "no")
5676 (const_int 4096)
5677 (const_int 4094)))
5678 (set (attr "neg_pool_range")
5679 (if_then_else (eq_attr "is_thumb" "no")
5680 (const_int 4084)
5681 (const_int 0)))]
5682 )
5683
5684 (define_insn "pic_load_addr_thumb1"
5685 [(set (match_operand:SI 0 "s_register_operand" "=l")
5686 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5687 "TARGET_THUMB1 && flag_pic"
5688 "ldr\\t%0, %1"
5689 [(set_attr "type" "load_4")
5690 (set (attr "pool_range") (const_int 1018))]
5691 )
5692
5693 (define_insn "pic_add_dot_plus_four"
5694 [(set (match_operand:SI 0 "register_operand" "=r")
5695 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5696 (const_int 4)
5697 (match_operand 2 "" "")]
5698 UNSPEC_PIC_BASE))]
5699 "TARGET_THUMB"
5700 "*
5701 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5702 INTVAL (operands[2]));
5703 return \"add\\t%0, %|pc\";
5704 "
5705 [(set_attr "length" "2")
5706 (set_attr "type" "alu_sreg")]
5707 )
5708
5709 (define_insn "pic_add_dot_plus_eight"
5710 [(set (match_operand:SI 0 "register_operand" "=r")
5711 (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5712 (const_int 8)
5713 (match_operand 2 "" "")]
5714 UNSPEC_PIC_BASE))]
5715 "TARGET_ARM"
5716 "*
5717 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5718 INTVAL (operands[2]));
5719 return \"add%?\\t%0, %|pc, %1\";
5720 "
5721 [(set_attr "predicable" "yes")
5722 (set_attr "type" "alu_sreg")]
5723 )
5724
5725 (define_insn "tls_load_dot_plus_eight"
5726 [(set (match_operand:SI 0 "register_operand" "=r")
5727 (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5728 (const_int 8)
5729 (match_operand 2 "" "")]
5730 UNSPEC_PIC_BASE)))]
5731 "TARGET_ARM"
5732 "*
5733 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5734 INTVAL (operands[2]));
5735 return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5736 "
5737 [(set_attr "predicable" "yes")
5738 (set_attr "type" "load_4")]
5739 )
5740
5741 ;; PIC references to local variables can generate pic_add_dot_plus_eight
5742 ;; followed by a load. These sequences can be crunched down to
5743 ;; tls_load_dot_plus_eight by a peephole.
5744
5745 (define_peephole2
5746 [(set (match_operand:SI 0 "register_operand" "")
5747 (unspec:SI [(match_operand:SI 3 "register_operand" "")
5748 (const_int 8)
5749 (match_operand 1 "" "")]
5750 UNSPEC_PIC_BASE))
5751 (set (match_operand:SI 2 "arm_general_register_operand" "")
5752 (mem:SI (match_dup 0)))]
5753 "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5754 [(set (match_dup 2)
5755 (mem:SI (unspec:SI [(match_dup 3)
5756 (const_int 8)
5757 (match_dup 1)]
5758 UNSPEC_PIC_BASE)))]
5759 ""
5760 )
5761
5762 (define_insn "pic_offset_arm"
5763 [(set (match_operand:SI 0 "register_operand" "=r")
5764 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5765 (unspec:SI [(match_operand:SI 2 "" "X")]
5766 UNSPEC_PIC_OFFSET))))]
5767 "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5768 "ldr%?\\t%0, [%1,%2]"
5769 [(set_attr "type" "load_4")]
5770 )
5771
5772 (define_expand "builtin_setjmp_receiver"
5773 [(label_ref (match_operand 0 "" ""))]
5774 "flag_pic"
5775 "
5776 {
5777 /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5778 register. */
5779 if (arm_pic_register != INVALID_REGNUM)
5780 arm_load_pic_register (1UL << 3, NULL_RTX);
5781 DONE;
5782 }")
5783
5784 ;; If copying one reg to another we can set the condition codes according to
5785 ;; its value. Such a move is common after a return from subroutine and the
5786 ;; result is being tested against zero.
5787
5788 (define_insn "*movsi_compare0"
5789 [(set (reg:CC CC_REGNUM)
5790 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5791 (const_int 0)))
5792 (set (match_operand:SI 0 "s_register_operand" "=r,r")
5793 (match_dup 1))]
5794 "TARGET_32BIT"
5795 "@
5796 cmp%?\\t%0, #0
5797 subs%?\\t%0, %1, #0"
5798 [(set_attr "conds" "set")
5799 (set_attr "type" "alus_imm,alus_imm")]
5800 )
5801
5802 ;; Subroutine to store a half word from a register into memory.
5803 ;; Operand 0 is the source register (HImode)
5804 ;; Operand 1 is the destination address in a register (SImode)
5805
5806 ;; In both this routine and the next, we must be careful not to spill
5807 ;; a memory address of reg+large_const into a separate PLUS insn, since this
5808 ;; can generate unrecognizable rtl.
5809
5810 (define_expand "storehi"
5811 [;; store the low byte
5812 (set (match_operand 1 "" "") (match_dup 3))
5813 ;; extract the high byte
5814 (set (match_dup 2)
5815 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5816 ;; store the high byte
5817 (set (match_dup 4) (match_dup 5))]
5818 "TARGET_ARM"
5819 "
5820 {
5821 rtx op1 = operands[1];
5822 rtx addr = XEXP (op1, 0);
5823 enum rtx_code code = GET_CODE (addr);
5824
5825 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5826 || code == MINUS)
5827 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5828
5829 operands[4] = adjust_address (op1, QImode, 1);
5830 operands[1] = adjust_address (operands[1], QImode, 0);
5831 operands[3] = gen_lowpart (QImode, operands[0]);
5832 operands[0] = gen_lowpart (SImode, operands[0]);
5833 operands[2] = gen_reg_rtx (SImode);
5834 operands[5] = gen_lowpart (QImode, operands[2]);
5835 }"
5836 )
5837
5838 (define_expand "storehi_bigend"
5839 [(set (match_dup 4) (match_dup 3))
5840 (set (match_dup 2)
5841 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5842 (set (match_operand 1 "" "") (match_dup 5))]
5843 "TARGET_ARM"
5844 "
5845 {
5846 rtx op1 = operands[1];
5847 rtx addr = XEXP (op1, 0);
5848 enum rtx_code code = GET_CODE (addr);
5849
5850 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5851 || code == MINUS)
5852 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5853
5854 operands[4] = adjust_address (op1, QImode, 1);
5855 operands[1] = adjust_address (operands[1], QImode, 0);
5856 operands[3] = gen_lowpart (QImode, operands[0]);
5857 operands[0] = gen_lowpart (SImode, operands[0]);
5858 operands[2] = gen_reg_rtx (SImode);
5859 operands[5] = gen_lowpart (QImode, operands[2]);
5860 }"
5861 )
5862
5863 ;; Subroutine to store a half word integer constant into memory.
5864 (define_expand "storeinthi"
5865 [(set (match_operand 0 "" "")
5866 (match_operand 1 "" ""))
5867 (set (match_dup 3) (match_dup 2))]
5868 "TARGET_ARM"
5869 "
5870 {
5871 HOST_WIDE_INT value = INTVAL (operands[1]);
5872 rtx addr = XEXP (operands[0], 0);
5873 rtx op0 = operands[0];
5874 enum rtx_code code = GET_CODE (addr);
5875
5876 if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
5877 || code == MINUS)
5878 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5879
5880 operands[1] = gen_reg_rtx (SImode);
5881 if (BYTES_BIG_ENDIAN)
5882 {
5883 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5884 if ((value & 255) == ((value >> 8) & 255))
5885 operands[2] = operands[1];
5886 else
5887 {
5888 operands[2] = gen_reg_rtx (SImode);
5889 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5890 }
5891 }
5892 else
5893 {
5894 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5895 if ((value & 255) == ((value >> 8) & 255))
5896 operands[2] = operands[1];
5897 else
5898 {
5899 operands[2] = gen_reg_rtx (SImode);
5900 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5901 }
5902 }
5903
5904 operands[3] = adjust_address (op0, QImode, 1);
5905 operands[0] = adjust_address (operands[0], QImode, 0);
5906 operands[2] = gen_lowpart (QImode, operands[2]);
5907 operands[1] = gen_lowpart (QImode, operands[1]);
5908 }"
5909 )
5910
5911 (define_expand "storehi_single_op"
5912 [(set (match_operand:HI 0 "memory_operand")
5913 (match_operand:HI 1 "general_operand"))]
5914 "TARGET_32BIT && arm_arch4"
5915 "
5916 if (!s_register_operand (operands[1], HImode))
5917 operands[1] = copy_to_mode_reg (HImode, operands[1]);
5918 "
5919 )
5920
5921 (define_expand "movhi"
5922 [(set (match_operand:HI 0 "general_operand")
5923 (match_operand:HI 1 "general_operand"))]
5924 "TARGET_EITHER"
5925 "
5926 gcc_checking_assert (aligned_operand (operands[0], HImode));
5927 gcc_checking_assert (aligned_operand (operands[1], HImode));
5928 if (TARGET_ARM)
5929 {
5930 if (can_create_pseudo_p ())
5931 {
5932 if (MEM_P (operands[0]))
5933 {
5934 if (arm_arch4)
5935 {
5936 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5937 DONE;
5938 }
5939 if (CONST_INT_P (operands[1]))
5940 emit_insn (gen_storeinthi (operands[0], operands[1]));
5941 else
5942 {
5943 if (MEM_P (operands[1]))
5944 operands[1] = force_reg (HImode, operands[1]);
5945 if (BYTES_BIG_ENDIAN)
5946 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5947 else
5948 emit_insn (gen_storehi (operands[1], operands[0]));
5949 }
5950 DONE;
5951 }
5952 /* Sign extend a constant, and keep it in an SImode reg. */
5953 else if (CONST_INT_P (operands[1]))
5954 {
5955 rtx reg = gen_reg_rtx (SImode);
5956 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5957
5958 /* If the constant is already valid, leave it alone. */
5959 if (!const_ok_for_arm (val))
5960 {
5961 /* If setting all the top bits will make the constant
5962 loadable in a single instruction, then set them.
5963 Otherwise, sign extend the number. */
5964
5965 if (const_ok_for_arm (~(val | ~0xffff)))
5966 val |= ~0xffff;
5967 else if (val & 0x8000)
5968 val |= ~0xffff;
5969 }
5970
5971 emit_insn (gen_movsi (reg, GEN_INT (val)));
5972 operands[1] = gen_lowpart (HImode, reg);
5973 }
5974 else if (arm_arch4 && optimize && can_create_pseudo_p ()
5975 && MEM_P (operands[1]))
5976 {
5977 rtx reg = gen_reg_rtx (SImode);
5978
5979 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5980 operands[1] = gen_lowpart (HImode, reg);
5981 }
5982 else if (!arm_arch4)
5983 {
5984 if (MEM_P (operands[1]))
5985 {
5986 rtx base;
5987 rtx offset = const0_rtx;
5988 rtx reg = gen_reg_rtx (SImode);
5989
5990 if ((REG_P (base = XEXP (operands[1], 0))
5991 || (GET_CODE (base) == PLUS
5992 && (CONST_INT_P (offset = XEXP (base, 1)))
5993 && ((INTVAL(offset) & 1) != 1)
5994 && REG_P (base = XEXP (base, 0))))
5995 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5996 {
5997 rtx new_rtx;
5998
5999 new_rtx = widen_memory_access (operands[1], SImode,
6000 ((INTVAL (offset) & ~3)
6001 - INTVAL (offset)));
6002 emit_insn (gen_movsi (reg, new_rtx));
6003 if (((INTVAL (offset) & 2) != 0)
6004 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6005 {
6006 rtx reg2 = gen_reg_rtx (SImode);
6007
6008 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6009 reg = reg2;
6010 }
6011 }
6012 else
6013 emit_insn (gen_movhi_bytes (reg, operands[1]));
6014
6015 operands[1] = gen_lowpart (HImode, reg);
6016 }
6017 }
6018 }
6019 /* Handle loading a large integer during reload. */
6020 else if (CONST_INT_P (operands[1])
6021 && !const_ok_for_arm (INTVAL (operands[1]))
6022 && !const_ok_for_arm (~INTVAL (operands[1])))
6023 {
6024 /* Writing a constant to memory needs a scratch, which should
6025 be handled with SECONDARY_RELOADs. */
6026 gcc_assert (REG_P (operands[0]));
6027
6028 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6029 emit_insn (gen_movsi (operands[0], operands[1]));
6030 DONE;
6031 }
6032 }
6033 else if (TARGET_THUMB2)
6034 {
6035 /* Thumb-2 can do everything except mem=mem and mem=const easily. */
6036 if (can_create_pseudo_p ())
6037 {
6038 if (!REG_P (operands[0]))
6039 operands[1] = force_reg (HImode, operands[1]);
6040 /* Zero extend a constant, and keep it in an SImode reg. */
6041 else if (CONST_INT_P (operands[1]))
6042 {
6043 rtx reg = gen_reg_rtx (SImode);
6044 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6045
6046 emit_insn (gen_movsi (reg, GEN_INT (val)));
6047 operands[1] = gen_lowpart (HImode, reg);
6048 }
6049 }
6050 }
6051 else /* TARGET_THUMB1 */
6052 {
6053 if (can_create_pseudo_p ())
6054 {
6055 if (CONST_INT_P (operands[1]))
6056 {
6057 rtx reg = gen_reg_rtx (SImode);
6058
6059 emit_insn (gen_movsi (reg, operands[1]));
6060 operands[1] = gen_lowpart (HImode, reg);
6061 }
6062
6063 /* ??? We shouldn't really get invalid addresses here, but this can
6064 happen if we are passed a SP (never OK for HImode/QImode) or
6065 virtual register (also rejected as illegitimate for HImode/QImode)
6066 relative address. */
6067 /* ??? This should perhaps be fixed elsewhere, for instance, in
6068 fixup_stack_1, by checking for other kinds of invalid addresses,
6069 e.g. a bare reference to a virtual register. This may confuse the
6070 alpha though, which must handle this case differently. */
6071 if (MEM_P (operands[0])
6072 && !memory_address_p (GET_MODE (operands[0]),
6073 XEXP (operands[0], 0)))
6074 operands[0]
6075 = replace_equiv_address (operands[0],
6076 copy_to_reg (XEXP (operands[0], 0)));
6077
6078 if (MEM_P (operands[1])
6079 && !memory_address_p (GET_MODE (operands[1]),
6080 XEXP (operands[1], 0)))
6081 operands[1]
6082 = replace_equiv_address (operands[1],
6083 copy_to_reg (XEXP (operands[1], 0)));
6084
6085 if (MEM_P (operands[1]) && optimize > 0)
6086 {
6087 rtx reg = gen_reg_rtx (SImode);
6088
6089 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6090 operands[1] = gen_lowpart (HImode, reg);
6091 }
6092
6093 if (MEM_P (operands[0]))
6094 operands[1] = force_reg (HImode, operands[1]);
6095 }
6096 else if (CONST_INT_P (operands[1])
6097 && !satisfies_constraint_I (operands[1]))
6098 {
6099 /* Handle loading a large integer during reload. */
6100
6101 /* Writing a constant to memory needs a scratch, which should
6102 be handled with SECONDARY_RELOADs. */
6103 gcc_assert (REG_P (operands[0]));
6104
6105 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6106 emit_insn (gen_movsi (operands[0], operands[1]));
6107 DONE;
6108 }
6109 }
6110 "
6111 )
6112
6113 (define_expand "movhi_bytes"
6114 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6115 (set (match_dup 3)
6116 (zero_extend:SI (match_dup 6)))
6117 (set (match_operand:SI 0 "" "")
6118 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6119 "TARGET_ARM"
6120 "
6121 {
6122 rtx mem1, mem2;
6123 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6124
6125 mem1 = change_address (operands[1], QImode, addr);
6126 mem2 = change_address (operands[1], QImode,
6127 plus_constant (Pmode, addr, 1));
6128 operands[0] = gen_lowpart (SImode, operands[0]);
6129 operands[1] = mem1;
6130 operands[2] = gen_reg_rtx (SImode);
6131 operands[3] = gen_reg_rtx (SImode);
6132 operands[6] = mem2;
6133
6134 if (BYTES_BIG_ENDIAN)
6135 {
6136 operands[4] = operands[2];
6137 operands[5] = operands[3];
6138 }
6139 else
6140 {
6141 operands[4] = operands[3];
6142 operands[5] = operands[2];
6143 }
6144 }"
6145 )
6146
6147 (define_expand "movhi_bigend"
6148 [(set (match_dup 2)
6149 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
6150 (const_int 16)))
6151 (set (match_dup 3)
6152 (ashiftrt:SI (match_dup 2) (const_int 16)))
6153 (set (match_operand:HI 0 "s_register_operand")
6154 (match_dup 4))]
6155 "TARGET_ARM"
6156 "
6157 operands[2] = gen_reg_rtx (SImode);
6158 operands[3] = gen_reg_rtx (SImode);
6159 operands[4] = gen_lowpart (HImode, operands[3]);
6160 "
6161 )
6162
6163 ;; Pattern to recognize insn generated default case above
6164 (define_insn "*movhi_insn_arch4"
6165 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
6166 (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
6167 "TARGET_ARM
6168 && arm_arch4 && !TARGET_HARD_FLOAT
6169 && (register_operand (operands[0], HImode)
6170 || register_operand (operands[1], HImode))"
6171 "@
6172 mov%?\\t%0, %1\\t%@ movhi
6173 mvn%?\\t%0, #%B1\\t%@ movhi
6174 movw%?\\t%0, %L1\\t%@ movhi
6175 strh%?\\t%1, %0\\t%@ movhi
6176 ldrh%?\\t%0, %1\\t%@ movhi"
6177 [(set_attr "predicable" "yes")
6178 (set_attr "pool_range" "*,*,*,*,256")
6179 (set_attr "neg_pool_range" "*,*,*,*,244")
6180 (set_attr "arch" "*,*,v6t2,*,*")
6181 (set_attr_alternative "type"
6182 [(if_then_else (match_operand 1 "const_int_operand" "")
6183 (const_string "mov_imm" )
6184 (const_string "mov_reg"))
6185 (const_string "mvn_imm")
6186 (const_string "mov_imm")
6187 (const_string "store_4")
6188 (const_string "load_4")])]
6189 )
6190
6191 (define_insn "*movhi_bytes"
6192 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
6193 (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
6194 "TARGET_ARM && !TARGET_HARD_FLOAT"
6195 "@
6196 mov%?\\t%0, %1\\t%@ movhi
6197 mov%?\\t%0, %1\\t%@ movhi
6198 mvn%?\\t%0, #%B1\\t%@ movhi"
6199 [(set_attr "predicable" "yes")
6200 (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
6201 )
6202
6203 ;; We use a DImode scratch because we may occasionally need an additional
6204 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
6205 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
6206 ;; The reload_in<m> and reload_out<m> patterns require special constraints
6207 ;; to be correctly handled in default_secondary_reload function.
6208 (define_expand "reload_outhi"
6209 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6210 (match_operand:HI 1 "s_register_operand" "r")
6211 (match_operand:DI 2 "s_register_operand" "=&l")])]
6212 "TARGET_EITHER"
6213 "if (TARGET_ARM)
6214 arm_reload_out_hi (operands);
6215 else
6216 thumb_reload_out_hi (operands);
6217 DONE;
6218 "
6219 )
6220
6221 (define_expand "reload_inhi"
6222 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6223 (match_operand:HI 1 "arm_reload_memory_operand" "o")
6224 (match_operand:DI 2 "s_register_operand" "=&r")])]
6225 "TARGET_EITHER"
6226 "
6227 if (TARGET_ARM)
6228 arm_reload_in_hi (operands);
6229 else
6230 thumb_reload_out_hi (operands);
6231 DONE;
6232 ")
6233
6234 (define_expand "movqi"
6235 [(set (match_operand:QI 0 "general_operand")
6236 (match_operand:QI 1 "general_operand"))]
6237 "TARGET_EITHER"
6238 "
6239 /* Everything except mem = const or mem = mem can be done easily */
6240
6241 if (can_create_pseudo_p ())
6242 {
6243 if (CONST_INT_P (operands[1]))
6244 {
6245 rtx reg = gen_reg_rtx (SImode);
6246
6247 /* For thumb we want an unsigned immediate, then we are more likely
6248 to be able to use a movs insn. */
6249 if (TARGET_THUMB)
6250 operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6251
6252 emit_insn (gen_movsi (reg, operands[1]));
6253 operands[1] = gen_lowpart (QImode, reg);
6254 }
6255
6256 if (TARGET_THUMB)
6257 {
6258 /* ??? We shouldn't really get invalid addresses here, but this can
6259 happen if we are passed a SP (never OK for HImode/QImode) or
6260 virtual register (also rejected as illegitimate for HImode/QImode)
6261 relative address. */
6262 /* ??? This should perhaps be fixed elsewhere, for instance, in
6263 fixup_stack_1, by checking for other kinds of invalid addresses,
6264 e.g. a bare reference to a virtual register. This may confuse the
6265 alpha though, which must handle this case differently. */
6266 if (MEM_P (operands[0])
6267 && !memory_address_p (GET_MODE (operands[0]),
6268 XEXP (operands[0], 0)))
6269 operands[0]
6270 = replace_equiv_address (operands[0],
6271 copy_to_reg (XEXP (operands[0], 0)));
6272 if (MEM_P (operands[1])
6273 && !memory_address_p (GET_MODE (operands[1]),
6274 XEXP (operands[1], 0)))
6275 operands[1]
6276 = replace_equiv_address (operands[1],
6277 copy_to_reg (XEXP (operands[1], 0)));
6278 }
6279
6280 if (MEM_P (operands[1]) && optimize > 0)
6281 {
6282 rtx reg = gen_reg_rtx (SImode);
6283
6284 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6285 operands[1] = gen_lowpart (QImode, reg);
6286 }
6287
6288 if (MEM_P (operands[0]))
6289 operands[1] = force_reg (QImode, operands[1]);
6290 }
6291 else if (TARGET_THUMB
6292 && CONST_INT_P (operands[1])
6293 && !satisfies_constraint_I (operands[1]))
6294 {
6295 /* Handle loading a large integer during reload. */
6296
6297 /* Writing a constant to memory needs a scratch, which should
6298 be handled with SECONDARY_RELOADs. */
6299 gcc_assert (REG_P (operands[0]));
6300
6301 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6302 emit_insn (gen_movsi (operands[0], operands[1]));
6303 DONE;
6304 }
6305 "
6306 )
6307
6308 (define_insn "*arm_movqi_insn"
6309 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
6310 (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
6311 "TARGET_32BIT
6312 && ( register_operand (operands[0], QImode)
6313 || register_operand (operands[1], QImode))"
6314 "@
6315 mov%?\\t%0, %1
6316 mov%?\\t%0, %1
6317 mov%?\\t%0, %1
6318 mov%?\\t%0, %1
6319 mvn%?\\t%0, #%B1
6320 ldrb%?\\t%0, %1
6321 strb%?\\t%1, %0
6322 ldrb%?\\t%0, %1
6323 strb%?\\t%1, %0"
6324 [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load_4,store_4,load_4,store_4")
6325 (set_attr "predicable" "yes")
6326 (set_attr "predicable_short_it" "yes,yes,no,yes,no,no,no,no,no")
6327 (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6328 (set_attr "length" "2,4,4,2,4,2,2,4,4")]
6329 )
6330
6331 ;; HFmode moves
6332 (define_expand "movhf"
6333 [(set (match_operand:HF 0 "general_operand")
6334 (match_operand:HF 1 "general_operand"))]
6335 "TARGET_EITHER"
6336 "
6337 gcc_checking_assert (aligned_operand (operands[0], HFmode));
6338 gcc_checking_assert (aligned_operand (operands[1], HFmode));
6339 if (TARGET_32BIT)
6340 {
6341 if (MEM_P (operands[0]))
6342 operands[1] = force_reg (HFmode, operands[1]);
6343 }
6344 else /* TARGET_THUMB1 */
6345 {
6346 if (can_create_pseudo_p ())
6347 {
6348 if (!REG_P (operands[0]))
6349 operands[1] = force_reg (HFmode, operands[1]);
6350 }
6351 }
6352 "
6353 )
6354
6355 (define_insn "*arm32_movhf"
6356 [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6357 (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6358 "TARGET_32BIT && !TARGET_HARD_FLOAT
6359 && ( s_register_operand (operands[0], HFmode)
6360 || s_register_operand (operands[1], HFmode))"
6361 "*
6362 switch (which_alternative)
6363 {
6364 case 0: /* ARM register from memory */
6365 return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
6366 case 1: /* memory from ARM register */
6367 return \"strh%?\\t%1, %0\\t%@ __fp16\";
6368 case 2: /* ARM register from ARM register */
6369 return \"mov%?\\t%0, %1\\t%@ __fp16\";
6370 case 3: /* ARM register from constant */
6371 {
6372 long bits;
6373 rtx ops[4];
6374
6375 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
6376 HFmode);
6377 ops[0] = operands[0];
6378 ops[1] = GEN_INT (bits);
6379 ops[2] = GEN_INT (bits & 0xff00);
6380 ops[3] = GEN_INT (bits & 0x00ff);
6381
6382 if (arm_arch_thumb2)
6383 output_asm_insn (\"movw%?\\t%0, %1\", ops);
6384 else
6385 output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6386 return \"\";
6387 }
6388 default:
6389 gcc_unreachable ();
6390 }
6391 "
6392 [(set_attr "conds" "unconditional")
6393 (set_attr "type" "load_4,store_4,mov_reg,multiple")
6394 (set_attr "length" "4,4,4,8")
6395 (set_attr "predicable" "yes")]
6396 )
6397
6398 (define_expand "movsf"
6399 [(set (match_operand:SF 0 "general_operand")
6400 (match_operand:SF 1 "general_operand"))]
6401 "TARGET_EITHER"
6402 "
6403 gcc_checking_assert (aligned_operand (operands[0], SFmode));
6404 gcc_checking_assert (aligned_operand (operands[1], SFmode));
6405 if (TARGET_32BIT)
6406 {
6407 if (MEM_P (operands[0]))
6408 operands[1] = force_reg (SFmode, operands[1]);
6409 }
6410 else /* TARGET_THUMB1 */
6411 {
6412 if (can_create_pseudo_p ())
6413 {
6414 if (!REG_P (operands[0]))
6415 operands[1] = force_reg (SFmode, operands[1]);
6416 }
6417 }
6418
6419 /* Cannot load it directly, generate a load with clobber so that it can be
6420 loaded via GPR with MOV / MOVT. */
6421 if (arm_disable_literal_pool
6422 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6423 && CONST_DOUBLE_P (operands[1])
6424 && TARGET_HARD_FLOAT
6425 && !vfp3_const_double_rtx (operands[1]))
6426 {
6427 rtx clobreg = gen_reg_rtx (SFmode);
6428 emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
6429 clobreg));
6430 DONE;
6431 }
6432 "
6433 )
6434
6435 ;; Transform a floating-point move of a constant into a core register into
6436 ;; an SImode operation.
6437 (define_split
6438 [(set (match_operand:SF 0 "arm_general_register_operand" "")
6439 (match_operand:SF 1 "immediate_operand" ""))]
6440 "TARGET_EITHER
6441 && reload_completed
6442 && CONST_DOUBLE_P (operands[1])"
6443 [(set (match_dup 2) (match_dup 3))]
6444 "
6445 operands[2] = gen_lowpart (SImode, operands[0]);
6446 operands[3] = gen_lowpart (SImode, operands[1]);
6447 if (operands[2] == 0 || operands[3] == 0)
6448 FAIL;
6449 "
6450 )
6451
6452 (define_insn "*arm_movsf_soft_insn"
6453 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6454 (match_operand:SF 1 "general_operand" "r,mE,r"))]
6455 "TARGET_32BIT
6456 && TARGET_SOFT_FLOAT
6457 && (!MEM_P (operands[0])
6458 || register_operand (operands[1], SFmode))"
6459 {
6460 switch (which_alternative)
6461 {
6462 case 0: return \"mov%?\\t%0, %1\";
6463 case 1:
6464 /* Cannot load it directly, split to load it via MOV / MOVT. */
6465 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6466 return \"#\";
6467 return \"ldr%?\\t%0, %1\\t%@ float\";
6468 case 2: return \"str%?\\t%1, %0\\t%@ float\";
6469 default: gcc_unreachable ();
6470 }
6471 }
6472 [(set_attr "predicable" "yes")
6473 (set_attr "type" "mov_reg,load_4,store_4")
6474 (set_attr "arm_pool_range" "*,4096,*")
6475 (set_attr "thumb2_pool_range" "*,4094,*")
6476 (set_attr "arm_neg_pool_range" "*,4084,*")
6477 (set_attr "thumb2_neg_pool_range" "*,0,*")]
6478 )
6479
6480 ;; Splitter for the above.
6481 (define_split
6482 [(set (match_operand:SF 0 "s_register_operand")
6483 (match_operand:SF 1 "const_double_operand"))]
6484 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6485 [(const_int 0)]
6486 {
6487 long buf;
6488 real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
6489 rtx cst = gen_int_mode (buf, SImode);
6490 emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
6491 DONE;
6492 }
6493 )
6494
6495 (define_expand "movdf"
6496 [(set (match_operand:DF 0 "general_operand")
6497 (match_operand:DF 1 "general_operand"))]
6498 "TARGET_EITHER"
6499 "
6500 gcc_checking_assert (aligned_operand (operands[0], DFmode));
6501 gcc_checking_assert (aligned_operand (operands[1], DFmode));
6502 if (TARGET_32BIT)
6503 {
6504 if (MEM_P (operands[0]))
6505 operands[1] = force_reg (DFmode, operands[1]);
6506 }
6507 else /* TARGET_THUMB */
6508 {
6509 if (can_create_pseudo_p ())
6510 {
6511 if (!REG_P (operands[0]))
6512 operands[1] = force_reg (DFmode, operands[1]);
6513 }
6514 }
6515
6516 /* Cannot load it directly, generate a load with clobber so that it can be
6517 loaded via GPR with MOV / MOVT. */
6518 if (arm_disable_literal_pool
6519 && (REG_P (operands[0]) || SUBREG_P (operands[0]))
6520 && CONSTANT_P (operands[1])
6521 && TARGET_HARD_FLOAT
6522 && !arm_const_double_rtx (operands[1])
6523 && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
6524 {
6525 rtx clobreg = gen_reg_rtx (DFmode);
6526 emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
6527 clobreg));
6528 DONE;
6529 }
6530 "
6531 )
6532
6533 ;; Reloading a df mode value stored in integer regs to memory can require a
6534 ;; scratch reg.
6535 ;; Another reload_out<m> pattern that requires special constraints.
6536 (define_expand "reload_outdf"
6537 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6538 (match_operand:DF 1 "s_register_operand" "r")
6539 (match_operand:SI 2 "s_register_operand" "=&r")]
6540 "TARGET_THUMB2"
6541 "
6542 {
6543 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6544
6545 if (code == REG)
6546 operands[2] = XEXP (operands[0], 0);
6547 else if (code == POST_INC || code == PRE_DEC)
6548 {
6549 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6550 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6551 emit_insn (gen_movdi (operands[0], operands[1]));
6552 DONE;
6553 }
6554 else if (code == PRE_INC)
6555 {
6556 rtx reg = XEXP (XEXP (operands[0], 0), 0);
6557
6558 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6559 operands[2] = reg;
6560 }
6561 else if (code == POST_DEC)
6562 operands[2] = XEXP (XEXP (operands[0], 0), 0);
6563 else
6564 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6565 XEXP (XEXP (operands[0], 0), 1)));
6566
6567 emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
6568 operands[1]));
6569
6570 if (code == POST_DEC)
6571 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6572
6573 DONE;
6574 }"
6575 )
6576
6577 (define_insn "*movdf_soft_insn"
6578 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6579 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6580 "TARGET_32BIT && TARGET_SOFT_FLOAT
6581 && ( register_operand (operands[0], DFmode)
6582 || register_operand (operands[1], DFmode))"
6583 "*
6584 switch (which_alternative)
6585 {
6586 case 0:
6587 case 1:
6588 case 2:
6589 return \"#\";
6590 case 3:
6591 /* Cannot load it directly, split to load it via MOV / MOVT. */
6592 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
6593 return \"#\";
6594 /* Fall through. */
6595 default:
6596 return output_move_double (operands, true, NULL);
6597 }
6598 "
6599 [(set_attr "length" "8,12,16,8,8")
6600 (set_attr "type" "multiple,multiple,multiple,load_8,store_8")
6601 (set_attr "arm_pool_range" "*,*,*,1020,*")
6602 (set_attr "thumb2_pool_range" "*,*,*,1018,*")
6603 (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
6604 (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
6605 )
6606
6607 ;; Splitter for the above.
6608 (define_split
6609 [(set (match_operand:DF 0 "s_register_operand")
6610 (match_operand:DF 1 "const_double_operand"))]
6611 "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
6612 [(const_int 0)]
6613 {
6614 long buf[2];
6615 int order = BYTES_BIG_ENDIAN ? 1 : 0;
6616 real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
6617 unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
6618 ival |= (zext_hwi (buf[1 - order], 32) << 32);
6619 rtx cst = gen_int_mode (ival, DImode);
6620 emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
6621 DONE;
6622 }
6623 )
6624 \f
6625
6626 ;; load- and store-multiple insns
6627 ;; The arm can load/store any set of registers, provided that they are in
6628 ;; ascending order, but these expanders assume a contiguous set.
6629
6630 (define_expand "load_multiple"
6631 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6632 (match_operand:SI 1 "" ""))
6633 (use (match_operand:SI 2 "" ""))])]
6634 "TARGET_32BIT"
6635 {
6636 HOST_WIDE_INT offset = 0;
6637
6638 /* Support only fixed point registers. */
6639 if (!CONST_INT_P (operands[2])
6640 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
6641 || INTVAL (operands[2]) < 2
6642 || !MEM_P (operands[1])
6643 || !REG_P (operands[0])
6644 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6645 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6646 FAIL;
6647
6648 operands[3]
6649 = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6650 INTVAL (operands[2]),
6651 force_reg (SImode, XEXP (operands[1], 0)),
6652 FALSE, operands[1], &offset);
6653 })
6654
6655 (define_expand "store_multiple"
6656 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6657 (match_operand:SI 1 "" ""))
6658 (use (match_operand:SI 2 "" ""))])]
6659 "TARGET_32BIT"
6660 {
6661 HOST_WIDE_INT offset = 0;
6662
6663 /* Support only fixed point registers. */
6664 if (!CONST_INT_P (operands[2])
6665 || INTVAL (operands[2]) > MAX_LDM_STM_OPS
6666 || INTVAL (operands[2]) < 2
6667 || !REG_P (operands[1])
6668 || !MEM_P (operands[0])
6669 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6670 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6671 FAIL;
6672
6673 operands[3]
6674 = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6675 INTVAL (operands[2]),
6676 force_reg (SImode, XEXP (operands[0], 0)),
6677 FALSE, operands[0], &offset);
6678 })
6679
6680
6681 (define_expand "setmemsi"
6682 [(match_operand:BLK 0 "general_operand")
6683 (match_operand:SI 1 "const_int_operand")
6684 (match_operand:SI 2 "const_int_operand")
6685 (match_operand:SI 3 "const_int_operand")]
6686 "TARGET_32BIT"
6687 {
6688 if (arm_gen_setmem (operands))
6689 DONE;
6690
6691 FAIL;
6692 })
6693
6694
6695 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6696 ;; We could let this apply for blocks of less than this, but it clobbers so
6697 ;; many registers that there is then probably a better way.
6698
6699 (define_expand "cpymemqi"
6700 [(match_operand:BLK 0 "general_operand")
6701 (match_operand:BLK 1 "general_operand")
6702 (match_operand:SI 2 "const_int_operand")
6703 (match_operand:SI 3 "const_int_operand")]
6704 ""
6705 "
6706 if (TARGET_32BIT)
6707 {
6708 if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6709 && !optimize_function_for_size_p (cfun))
6710 {
6711 if (gen_cpymem_ldrd_strd (operands))
6712 DONE;
6713 FAIL;
6714 }
6715
6716 if (arm_gen_cpymemqi (operands))
6717 DONE;
6718 FAIL;
6719 }
6720 else /* TARGET_THUMB1 */
6721 {
6722 if ( INTVAL (operands[3]) != 4
6723 || INTVAL (operands[2]) > 48)
6724 FAIL;
6725
6726 thumb_expand_cpymemqi (operands);
6727 DONE;
6728 }
6729 "
6730 )
6731 \f
6732
6733 ;; Compare & branch insns
6734 ;; The range calculations are based as follows:
6735 ;; For forward branches, the address calculation returns the address of
6736 ;; the next instruction. This is 2 beyond the branch instruction.
6737 ;; For backward branches, the address calculation returns the address of
6738 ;; the first instruction in this pattern (cmp). This is 2 before the branch
6739 ;; instruction for the shortest sequence, and 4 before the branch instruction
6740 ;; if we have to jump around an unconditional branch.
6741 ;; To the basic branch range the PC offset must be added (this is +4).
6742 ;; So for forward branches we have
6743 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6744 ;; And for backward branches we have
6745 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6746 ;;
6747 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6748 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
6749
6750 (define_expand "cbranchsi4"
6751 [(set (pc) (if_then_else
6752 (match_operator 0 "expandable_comparison_operator"
6753 [(match_operand:SI 1 "s_register_operand")
6754 (match_operand:SI 2 "nonmemory_operand")])
6755 (label_ref (match_operand 3 "" ""))
6756 (pc)))]
6757 "TARGET_EITHER"
6758 "
6759 if (!TARGET_THUMB1)
6760 {
6761 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6762 FAIL;
6763 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6764 operands[3]));
6765 DONE;
6766 }
6767 if (thumb1_cmpneg_operand (operands[2], SImode))
6768 {
6769 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6770 operands[3], operands[0]));
6771 DONE;
6772 }
6773 if (!thumb1_cmp_operand (operands[2], SImode))
6774 operands[2] = force_reg (SImode, operands[2]);
6775 ")
6776
6777 (define_expand "cbranchsf4"
6778 [(set (pc) (if_then_else
6779 (match_operator 0 "expandable_comparison_operator"
6780 [(match_operand:SF 1 "s_register_operand")
6781 (match_operand:SF 2 "vfp_compare_operand")])
6782 (label_ref (match_operand 3 "" ""))
6783 (pc)))]
6784 "TARGET_32BIT && TARGET_HARD_FLOAT"
6785 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6786 operands[3])); DONE;"
6787 )
6788
6789 (define_expand "cbranchdf4"
6790 [(set (pc) (if_then_else
6791 (match_operator 0 "expandable_comparison_operator"
6792 [(match_operand:DF 1 "s_register_operand")
6793 (match_operand:DF 2 "vfp_compare_operand")])
6794 (label_ref (match_operand 3 "" ""))
6795 (pc)))]
6796 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6797 "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6798 operands[3])); DONE;"
6799 )
6800
6801 (define_expand "cbranchdi4"
6802 [(set (pc) (if_then_else
6803 (match_operator 0 "expandable_comparison_operator"
6804 [(match_operand:DI 1 "s_register_operand")
6805 (match_operand:DI 2 "cmpdi_operand")])
6806 (label_ref (match_operand 3 "" ""))
6807 (pc)))]
6808 "TARGET_32BIT"
6809 "{
6810 if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6811 FAIL;
6812 emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6813 operands[3]));
6814 DONE;
6815 }"
6816 )
6817
6818 ;; Comparison and test insns
6819
6820 (define_insn "*arm_cmpsi_insn"
6821 [(set (reg:CC CC_REGNUM)
6822 (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6823 (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
6824 "TARGET_32BIT"
6825 "@
6826 cmp%?\\t%0, %1
6827 cmp%?\\t%0, %1
6828 cmp%?\\t%0, %1
6829 cmp%?\\t%0, %1
6830 cmn%?\\t%0, #%n1"
6831 [(set_attr "conds" "set")
6832 (set_attr "arch" "t2,t2,any,any,any")
6833 (set_attr "length" "2,2,4,4,4")
6834 (set_attr "predicable" "yes")
6835 (set_attr "predicable_short_it" "yes,yes,yes,no,no")
6836 (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
6837 )
6838
6839 (define_insn "*cmpsi_shiftsi"
6840 [(set (reg:CC CC_REGNUM)
6841 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
6842 (match_operator:SI 3 "shift_operator"
6843 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6844 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
6845 "TARGET_32BIT"
6846 "cmp\\t%0, %1%S3"
6847 [(set_attr "conds" "set")
6848 (set_attr "shift" "1")
6849 (set_attr "arch" "32,a,a")
6850 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
6851
6852 (define_insn "*cmpsi_shiftsi_swp"
6853 [(set (reg:CC_SWP CC_REGNUM)
6854 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6855 [(match_operand:SI 1 "s_register_operand" "r,r,r")
6856 (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6857 (match_operand:SI 0 "s_register_operand" "r,r,r")))]
6858 "TARGET_32BIT"
6859 "cmp%?\\t%0, %1%S3"
6860 [(set_attr "conds" "set")
6861 (set_attr "shift" "1")
6862 (set_attr "arch" "32,a,a")
6863 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
6864
6865 (define_insn "*arm_cmpsi_negshiftsi_si"
6866 [(set (reg:CC_Z CC_REGNUM)
6867 (compare:CC_Z
6868 (neg:SI (match_operator:SI 1 "shift_operator"
6869 [(match_operand:SI 2 "s_register_operand" "r")
6870 (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6871 (match_operand:SI 0 "s_register_operand" "r")))]
6872 "TARGET_ARM"
6873 "cmn%?\\t%0, %2%S1"
6874 [(set_attr "conds" "set")
6875 (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6876 (const_string "alus_shift_imm")
6877 (const_string "alus_shift_reg")))
6878 (set_attr "predicable" "yes")]
6879 )
6880
6881 ;; DImode comparisons. The generic code generates branches that
6882 ;; if-conversion cannot reduce to a conditional compare, so we do
6883 ;; that directly.
6884
6885 (define_insn_and_split "*arm_cmpdi_insn"
6886 [(set (reg:CC_NCV CC_REGNUM)
6887 (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
6888 (match_operand:DI 1 "arm_di_operand" "rDi")))
6889 (clobber (match_scratch:SI 2 "=r"))]
6890 "TARGET_32BIT"
6891 "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
6892 "&& reload_completed"
6893 [(set (reg:CC CC_REGNUM)
6894 (compare:CC (match_dup 0) (match_dup 1)))
6895 (parallel [(set (reg:CC CC_REGNUM)
6896 (compare:CC (match_dup 3) (match_dup 4)))
6897 (set (match_dup 2)
6898 (minus:SI (match_dup 5)
6899 (ltu:SI (reg:CC CC_REGNUM) (const_int 0))))])]
6900 {
6901 operands[3] = gen_highpart (SImode, operands[0]);
6902 operands[0] = gen_lowpart (SImode, operands[0]);
6903 if (CONST_INT_P (operands[1]))
6904 {
6905 operands[4] = gen_highpart_mode (SImode, DImode, operands[1]);
6906 if (operands[4] == const0_rtx)
6907 operands[5] = operands[3];
6908 else
6909 operands[5] = gen_rtx_PLUS (SImode, operands[3],
6910 gen_int_mode (-UINTVAL (operands[4]),
6911 SImode));
6912 }
6913 else
6914 {
6915 operands[4] = gen_highpart (SImode, operands[1]);
6916 operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
6917 }
6918 operands[1] = gen_lowpart (SImode, operands[1]);
6919 operands[2] = gen_lowpart (SImode, operands[2]);
6920 }
6921 [(set_attr "conds" "set")
6922 (set_attr "length" "8")
6923 (set_attr "type" "multiple")]
6924 )
6925
6926 (define_insn_and_split "*arm_cmpdi_unsigned"
6927 [(set (reg:CC_CZ CC_REGNUM)
6928 (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
6929 (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
6930
6931 "TARGET_32BIT"
6932 "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
6933 "&& reload_completed"
6934 [(set (reg:CC CC_REGNUM)
6935 (compare:CC (match_dup 2) (match_dup 3)))
6936 (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
6937 (set (reg:CC CC_REGNUM)
6938 (compare:CC (match_dup 0) (match_dup 1))))]
6939 {
6940 operands[2] = gen_highpart (SImode, operands[0]);
6941 operands[0] = gen_lowpart (SImode, operands[0]);
6942 if (CONST_INT_P (operands[1]))
6943 operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6944 else
6945 operands[3] = gen_highpart (SImode, operands[1]);
6946 operands[1] = gen_lowpart (SImode, operands[1]);
6947 }
6948 [(set_attr "conds" "set")
6949 (set_attr "enabled_for_short_it" "yes,yes,no,*")
6950 (set_attr "arch" "t2,t2,t2,a")
6951 (set_attr "length" "6,6,10,8")
6952 (set_attr "type" "multiple")]
6953 )
6954
6955 (define_insn "*arm_cmpdi_zero"
6956 [(set (reg:CC_Z CC_REGNUM)
6957 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
6958 (const_int 0)))
6959 (clobber (match_scratch:SI 1 "=r"))]
6960 "TARGET_32BIT"
6961 "orrs%?\\t%1, %Q0, %R0"
6962 [(set_attr "conds" "set")
6963 (set_attr "type" "logics_reg")]
6964 )
6965
6966 ; This insn allows redundant compares to be removed by cse, nothing should
6967 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6968 ; is deleted later on. The match_dup will match the mode here, so that
6969 ; mode changes of the condition codes aren't lost by this even though we don't
6970 ; specify what they are.
6971
6972 (define_insn "*deleted_compare"
6973 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6974 "TARGET_32BIT"
6975 "\\t%@ deleted compare"
6976 [(set_attr "conds" "set")
6977 (set_attr "length" "0")
6978 (set_attr "type" "no_insn")]
6979 )
6980
6981 \f
6982 ;; Conditional branch insns
6983
6984 (define_expand "cbranch_cc"
6985 [(set (pc)
6986 (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
6987 (match_operand 2 "" "")])
6988 (label_ref (match_operand 3 "" ""))
6989 (pc)))]
6990 "TARGET_32BIT"
6991 "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
6992 operands[1], operands[2], NULL_RTX);
6993 operands[2] = const0_rtx;"
6994 )
6995
6996 ;;
6997 ;; Patterns to match conditional branch insns.
6998 ;;
6999
7000 (define_insn "arm_cond_branch"
7001 [(set (pc)
7002 (if_then_else (match_operator 1 "arm_comparison_operator"
7003 [(match_operand 2 "cc_register" "") (const_int 0)])
7004 (label_ref (match_operand 0 "" ""))
7005 (pc)))]
7006 "TARGET_32BIT"
7007 "*
7008 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7009 {
7010 arm_ccfsm_state += 2;
7011 return \"\";
7012 }
7013 return \"b%d1\\t%l0\";
7014 "
7015 [(set_attr "conds" "use")
7016 (set_attr "type" "branch")
7017 (set (attr "length")
7018 (if_then_else
7019 (and (match_test "TARGET_THUMB2")
7020 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7021 (le (minus (match_dup 0) (pc)) (const_int 256))))
7022 (const_int 2)
7023 (const_int 4)))]
7024 )
7025
7026 (define_insn "*arm_cond_branch_reversed"
7027 [(set (pc)
7028 (if_then_else (match_operator 1 "arm_comparison_operator"
7029 [(match_operand 2 "cc_register" "") (const_int 0)])
7030 (pc)
7031 (label_ref (match_operand 0 "" ""))))]
7032 "TARGET_32BIT"
7033 "*
7034 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7035 {
7036 arm_ccfsm_state += 2;
7037 return \"\";
7038 }
7039 return \"b%D1\\t%l0\";
7040 "
7041 [(set_attr "conds" "use")
7042 (set_attr "type" "branch")
7043 (set (attr "length")
7044 (if_then_else
7045 (and (match_test "TARGET_THUMB2")
7046 (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7047 (le (minus (match_dup 0) (pc)) (const_int 256))))
7048 (const_int 2)
7049 (const_int 4)))]
7050 )
7051
7052 \f
7053
7054 ; scc insns
7055
7056 (define_expand "cstore_cc"
7057 [(set (match_operand:SI 0 "s_register_operand")
7058 (match_operator:SI 1 "" [(match_operand 2 "" "")
7059 (match_operand 3 "" "")]))]
7060 "TARGET_32BIT"
7061 "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7062 operands[2], operands[3], NULL_RTX);
7063 operands[3] = const0_rtx;"
7064 )
7065
7066 (define_insn_and_split "*mov_scc"
7067 [(set (match_operand:SI 0 "s_register_operand" "=r")
7068 (match_operator:SI 1 "arm_comparison_operator_mode"
7069 [(match_operand 2 "cc_register" "") (const_int 0)]))]
7070 "TARGET_ARM"
7071 "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7072 "TARGET_ARM"
7073 [(set (match_dup 0)
7074 (if_then_else:SI (match_dup 1)
7075 (const_int 1)
7076 (const_int 0)))]
7077 ""
7078 [(set_attr "conds" "use")
7079 (set_attr "length" "8")
7080 (set_attr "type" "multiple")]
7081 )
7082
7083 (define_insn_and_split "*mov_negscc"
7084 [(set (match_operand:SI 0 "s_register_operand" "=r")
7085 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
7086 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7087 "TARGET_ARM"
7088 "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7089 "TARGET_ARM"
7090 [(set (match_dup 0)
7091 (if_then_else:SI (match_dup 1)
7092 (match_dup 3)
7093 (const_int 0)))]
7094 {
7095 operands[3] = GEN_INT (~0);
7096 }
7097 [(set_attr "conds" "use")
7098 (set_attr "length" "8")
7099 (set_attr "type" "multiple")]
7100 )
7101
7102 (define_insn_and_split "*mov_notscc"
7103 [(set (match_operand:SI 0 "s_register_operand" "=r")
7104 (not:SI (match_operator:SI 1 "arm_comparison_operator"
7105 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7106 "TARGET_ARM"
7107 "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7108 "TARGET_ARM"
7109 [(set (match_dup 0)
7110 (if_then_else:SI (match_dup 1)
7111 (match_dup 3)
7112 (match_dup 4)))]
7113 {
7114 operands[3] = GEN_INT (~1);
7115 operands[4] = GEN_INT (~0);
7116 }
7117 [(set_attr "conds" "use")
7118 (set_attr "length" "8")
7119 (set_attr "type" "multiple")]
7120 )
7121
7122 (define_expand "cstoresi4"
7123 [(set (match_operand:SI 0 "s_register_operand")
7124 (match_operator:SI 1 "expandable_comparison_operator"
7125 [(match_operand:SI 2 "s_register_operand")
7126 (match_operand:SI 3 "reg_or_int_operand")]))]
7127 "TARGET_32BIT || TARGET_THUMB1"
7128 "{
7129 rtx op3, scratch, scratch2;
7130
7131 if (!TARGET_THUMB1)
7132 {
7133 if (!arm_add_operand (operands[3], SImode))
7134 operands[3] = force_reg (SImode, operands[3]);
7135 emit_insn (gen_cstore_cc (operands[0], operands[1],
7136 operands[2], operands[3]));
7137 DONE;
7138 }
7139
7140 if (operands[3] == const0_rtx)
7141 {
7142 switch (GET_CODE (operands[1]))
7143 {
7144 case EQ:
7145 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7146 break;
7147
7148 case NE:
7149 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7150 break;
7151
7152 case LE:
7153 scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7154 NULL_RTX, 0, OPTAB_WIDEN);
7155 scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7156 NULL_RTX, 0, OPTAB_WIDEN);
7157 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7158 operands[0], 1, OPTAB_WIDEN);
7159 break;
7160
7161 case GE:
7162 scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7163 NULL_RTX, 1);
7164 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7165 NULL_RTX, 1, OPTAB_WIDEN);
7166 break;
7167
7168 case GT:
7169 scratch = expand_binop (SImode, ashr_optab, operands[2],
7170 GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7171 scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7172 NULL_RTX, 0, OPTAB_WIDEN);
7173 expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7174 0, OPTAB_WIDEN);
7175 break;
7176
7177 /* LT is handled by generic code. No need for unsigned with 0. */
7178 default:
7179 FAIL;
7180 }
7181 DONE;
7182 }
7183
7184 switch (GET_CODE (operands[1]))
7185 {
7186 case EQ:
7187 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7188 NULL_RTX, 0, OPTAB_WIDEN);
7189 emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7190 break;
7191
7192 case NE:
7193 scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7194 NULL_RTX, 0, OPTAB_WIDEN);
7195 emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7196 break;
7197
7198 case LE:
7199 op3 = force_reg (SImode, operands[3]);
7200
7201 scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7202 NULL_RTX, 1, OPTAB_WIDEN);
7203 scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7204 NULL_RTX, 0, OPTAB_WIDEN);
7205 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7206 op3, operands[2]));
7207 break;
7208
7209 case GE:
7210 op3 = operands[3];
7211 if (!thumb1_cmp_operand (op3, SImode))
7212 op3 = force_reg (SImode, op3);
7213 scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7214 NULL_RTX, 0, OPTAB_WIDEN);
7215 scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7216 NULL_RTX, 1, OPTAB_WIDEN);
7217 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7218 operands[2], op3));
7219 break;
7220
7221 case LEU:
7222 op3 = force_reg (SImode, operands[3]);
7223 scratch = force_reg (SImode, const0_rtx);
7224 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7225 op3, operands[2]));
7226 break;
7227
7228 case GEU:
7229 op3 = operands[3];
7230 if (!thumb1_cmp_operand (op3, SImode))
7231 op3 = force_reg (SImode, op3);
7232 scratch = force_reg (SImode, const0_rtx);
7233 emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7234 operands[2], op3));
7235 break;
7236
7237 case LTU:
7238 op3 = operands[3];
7239 if (!thumb1_cmp_operand (op3, SImode))
7240 op3 = force_reg (SImode, op3);
7241 scratch = gen_reg_rtx (SImode);
7242 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7243 break;
7244
7245 case GTU:
7246 op3 = force_reg (SImode, operands[3]);
7247 scratch = gen_reg_rtx (SImode);
7248 emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7249 break;
7250
7251 /* No good sequences for GT, LT. */
7252 default:
7253 FAIL;
7254 }
7255 DONE;
7256 }")
7257
7258 (define_expand "cstorehf4"
7259 [(set (match_operand:SI 0 "s_register_operand")
7260 (match_operator:SI 1 "expandable_comparison_operator"
7261 [(match_operand:HF 2 "s_register_operand")
7262 (match_operand:HF 3 "vfp_compare_operand")]))]
7263 "TARGET_VFP_FP16INST"
7264 {
7265 if (!arm_validize_comparison (&operands[1],
7266 &operands[2],
7267 &operands[3]))
7268 FAIL;
7269
7270 emit_insn (gen_cstore_cc (operands[0], operands[1],
7271 operands[2], operands[3]));
7272 DONE;
7273 }
7274 )
7275
7276 (define_expand "cstoresf4"
7277 [(set (match_operand:SI 0 "s_register_operand")
7278 (match_operator:SI 1 "expandable_comparison_operator"
7279 [(match_operand:SF 2 "s_register_operand")
7280 (match_operand:SF 3 "vfp_compare_operand")]))]
7281 "TARGET_32BIT && TARGET_HARD_FLOAT"
7282 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7283 operands[2], operands[3])); DONE;"
7284 )
7285
7286 (define_expand "cstoredf4"
7287 [(set (match_operand:SI 0 "s_register_operand")
7288 (match_operator:SI 1 "expandable_comparison_operator"
7289 [(match_operand:DF 2 "s_register_operand")
7290 (match_operand:DF 3 "vfp_compare_operand")]))]
7291 "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7292 "emit_insn (gen_cstore_cc (operands[0], operands[1],
7293 operands[2], operands[3])); DONE;"
7294 )
7295
7296 (define_expand "cstoredi4"
7297 [(set (match_operand:SI 0 "s_register_operand")
7298 (match_operator:SI 1 "expandable_comparison_operator"
7299 [(match_operand:DI 2 "s_register_operand")
7300 (match_operand:DI 3 "cmpdi_operand")]))]
7301 "TARGET_32BIT"
7302 "{
7303 if (!arm_validize_comparison (&operands[1],
7304 &operands[2],
7305 &operands[3]))
7306 FAIL;
7307 emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7308 operands[3]));
7309 DONE;
7310 }"
7311 )
7312
7313 \f
7314 ;; Conditional move insns
7315
7316 (define_expand "movsicc"
7317 [(set (match_operand:SI 0 "s_register_operand")
7318 (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
7319 (match_operand:SI 2 "arm_not_operand")
7320 (match_operand:SI 3 "arm_not_operand")))]
7321 "TARGET_32BIT"
7322 "
7323 {
7324 enum rtx_code code;
7325 rtx ccreg;
7326
7327 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7328 &XEXP (operands[1], 1)))
7329 FAIL;
7330
7331 code = GET_CODE (operands[1]);
7332 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7333 XEXP (operands[1], 1), NULL_RTX);
7334 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7335 }"
7336 )
7337
7338 (define_expand "movhfcc"
7339 [(set (match_operand:HF 0 "s_register_operand")
7340 (if_then_else:HF (match_operand 1 "arm_cond_move_operator")
7341 (match_operand:HF 2 "s_register_operand")
7342 (match_operand:HF 3 "s_register_operand")))]
7343 "TARGET_VFP_FP16INST"
7344 "
7345 {
7346 enum rtx_code code = GET_CODE (operands[1]);
7347 rtx ccreg;
7348
7349 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7350 &XEXP (operands[1], 1)))
7351 FAIL;
7352
7353 code = GET_CODE (operands[1]);
7354 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7355 XEXP (operands[1], 1), NULL_RTX);
7356 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7357 }"
7358 )
7359
7360 (define_expand "movsfcc"
7361 [(set (match_operand:SF 0 "s_register_operand")
7362 (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
7363 (match_operand:SF 2 "s_register_operand")
7364 (match_operand:SF 3 "s_register_operand")))]
7365 "TARGET_32BIT && TARGET_HARD_FLOAT"
7366 "
7367 {
7368 enum rtx_code code = GET_CODE (operands[1]);
7369 rtx ccreg;
7370
7371 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7372 &XEXP (operands[1], 1)))
7373 FAIL;
7374
7375 code = GET_CODE (operands[1]);
7376 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7377 XEXP (operands[1], 1), NULL_RTX);
7378 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7379 }"
7380 )
7381
7382 (define_expand "movdfcc"
7383 [(set (match_operand:DF 0 "s_register_operand")
7384 (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
7385 (match_operand:DF 2 "s_register_operand")
7386 (match_operand:DF 3 "s_register_operand")))]
7387 "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
7388 "
7389 {
7390 enum rtx_code code = GET_CODE (operands[1]);
7391 rtx ccreg;
7392
7393 if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7394 &XEXP (operands[1], 1)))
7395 FAIL;
7396 code = GET_CODE (operands[1]);
7397 ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
7398 XEXP (operands[1], 1), NULL_RTX);
7399 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7400 }"
7401 )
7402
7403 (define_insn "*cmov<mode>"
7404 [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7405 (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7406 [(match_operand 2 "cc_register" "") (const_int 0)])
7407 (match_operand:SDF 3 "s_register_operand"
7408 "<F_constraint>")
7409 (match_operand:SDF 4 "s_register_operand"
7410 "<F_constraint>")))]
7411 "TARGET_HARD_FLOAT && TARGET_VFP5 <vfp_double_cond>"
7412 "*
7413 {
7414 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7415 switch (code)
7416 {
7417 case ARM_GE:
7418 case ARM_GT:
7419 case ARM_EQ:
7420 case ARM_VS:
7421 return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7422 case ARM_LT:
7423 case ARM_LE:
7424 case ARM_NE:
7425 case ARM_VC:
7426 return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7427 default:
7428 gcc_unreachable ();
7429 }
7430 return \"\";
7431 }"
7432 [(set_attr "conds" "use")
7433 (set_attr "type" "fcsel")]
7434 )
7435
7436 (define_insn "*cmovhf"
7437 [(set (match_operand:HF 0 "s_register_operand" "=t")
7438 (if_then_else:HF (match_operator 1 "arm_vsel_comparison_operator"
7439 [(match_operand 2 "cc_register" "") (const_int 0)])
7440 (match_operand:HF 3 "s_register_operand" "t")
7441 (match_operand:HF 4 "s_register_operand" "t")))]
7442 "TARGET_VFP_FP16INST"
7443 "*
7444 {
7445 enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7446 switch (code)
7447 {
7448 case ARM_GE:
7449 case ARM_GT:
7450 case ARM_EQ:
7451 case ARM_VS:
7452 return \"vsel%d1.f16\\t%0, %3, %4\";
7453 case ARM_LT:
7454 case ARM_LE:
7455 case ARM_NE:
7456 case ARM_VC:
7457 return \"vsel%D1.f16\\t%0, %4, %3\";
7458 default:
7459 gcc_unreachable ();
7460 }
7461 return \"\";
7462 }"
7463 [(set_attr "conds" "use")
7464 (set_attr "type" "fcsel")]
7465 )
7466
7467 (define_insn_and_split "*movsicc_insn"
7468 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7469 (if_then_else:SI
7470 (match_operator 3 "arm_comparison_operator"
7471 [(match_operand 4 "cc_register" "") (const_int 0)])
7472 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7473 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7474 "TARGET_ARM"
7475 "@
7476 mov%D3\\t%0, %2
7477 mvn%D3\\t%0, #%B2
7478 mov%d3\\t%0, %1
7479 mvn%d3\\t%0, #%B1
7480 #
7481 #
7482 #
7483 #"
7484 ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7485 ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7486 ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7487 ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7488 "&& reload_completed"
7489 [(const_int 0)]
7490 {
7491 enum rtx_code rev_code;
7492 machine_mode mode;
7493 rtx rev_cond;
7494
7495 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7496 operands[3],
7497 gen_rtx_SET (operands[0], operands[1])));
7498
7499 rev_code = GET_CODE (operands[3]);
7500 mode = GET_MODE (operands[4]);
7501 if (mode == CCFPmode || mode == CCFPEmode)
7502 rev_code = reverse_condition_maybe_unordered (rev_code);
7503 else
7504 rev_code = reverse_condition (rev_code);
7505
7506 rev_cond = gen_rtx_fmt_ee (rev_code,
7507 VOIDmode,
7508 operands[4],
7509 const0_rtx);
7510 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7511 rev_cond,
7512 gen_rtx_SET (operands[0], operands[2])));
7513 DONE;
7514 }
7515 [(set_attr "length" "4,4,4,4,8,8,8,8")
7516 (set_attr "conds" "use")
7517 (set_attr_alternative "type"
7518 [(if_then_else (match_operand 2 "const_int_operand" "")
7519 (const_string "mov_imm")
7520 (const_string "mov_reg"))
7521 (const_string "mvn_imm")
7522 (if_then_else (match_operand 1 "const_int_operand" "")
7523 (const_string "mov_imm")
7524 (const_string "mov_reg"))
7525 (const_string "mvn_imm")
7526 (const_string "multiple")
7527 (const_string "multiple")
7528 (const_string "multiple")
7529 (const_string "multiple")])]
7530 )
7531
7532 (define_insn "*movsfcc_soft_insn"
7533 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7534 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7535 [(match_operand 4 "cc_register" "") (const_int 0)])
7536 (match_operand:SF 1 "s_register_operand" "0,r")
7537 (match_operand:SF 2 "s_register_operand" "r,0")))]
7538 "TARGET_ARM && TARGET_SOFT_FLOAT"
7539 "@
7540 mov%D3\\t%0, %2
7541 mov%d3\\t%0, %1"
7542 [(set_attr "conds" "use")
7543 (set_attr "type" "mov_reg")]
7544 )
7545
7546 \f
7547 ;; Jump and linkage insns
7548
7549 (define_expand "jump"
7550 [(set (pc)
7551 (label_ref (match_operand 0 "" "")))]
7552 "TARGET_EITHER"
7553 ""
7554 )
7555
7556 (define_insn "*arm_jump"
7557 [(set (pc)
7558 (label_ref (match_operand 0 "" "")))]
7559 "TARGET_32BIT"
7560 "*
7561 {
7562 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7563 {
7564 arm_ccfsm_state += 2;
7565 return \"\";
7566 }
7567 return \"b%?\\t%l0\";
7568 }
7569 "
7570 [(set_attr "predicable" "yes")
7571 (set (attr "length")
7572 (if_then_else
7573 (and (match_test "TARGET_THUMB2")
7574 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7575 (le (minus (match_dup 0) (pc)) (const_int 2048))))
7576 (const_int 2)
7577 (const_int 4)))
7578 (set_attr "type" "branch")]
7579 )
7580
7581 (define_expand "call"
7582 [(parallel [(call (match_operand 0 "memory_operand")
7583 (match_operand 1 "general_operand"))
7584 (use (match_operand 2 "" ""))
7585 (clobber (reg:SI LR_REGNUM))])]
7586 "TARGET_EITHER"
7587 "
7588 {
7589 rtx callee, pat;
7590 tree addr = MEM_EXPR (operands[0]);
7591
7592 /* In an untyped call, we can get NULL for operand 2. */
7593 if (operands[2] == NULL_RTX)
7594 operands[2] = const0_rtx;
7595
7596 /* Decide if we should generate indirect calls by loading the
7597 32-bit address of the callee into a register before performing the
7598 branch and link. */
7599 callee = XEXP (operands[0], 0);
7600 if (GET_CODE (callee) == SYMBOL_REF
7601 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7602 : !REG_P (callee))
7603 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7604
7605 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[0], 0)))
7606 /* Indirect call: set r9 with FDPIC value of callee. */
7607 XEXP (operands[0], 0)
7608 = arm_load_function_descriptor (XEXP (operands[0], 0));
7609
7610 if (detect_cmse_nonsecure_call (addr))
7611 {
7612 pat = gen_nonsecure_call_internal (operands[0], operands[1],
7613 operands[2]);
7614 emit_call_insn (pat);
7615 }
7616 else
7617 {
7618 pat = gen_call_internal (operands[0], operands[1], operands[2]);
7619 arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
7620 }
7621
7622 /* Restore FDPIC register (r9) after call. */
7623 if (TARGET_FDPIC)
7624 {
7625 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7626 rtx initial_fdpic_reg
7627 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7628
7629 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7630 initial_fdpic_reg));
7631 }
7632
7633 DONE;
7634 }"
7635 )
7636
7637 (define_insn "restore_pic_register_after_call"
7638 [(set (match_operand:SI 0 "s_register_operand" "+r,r")
7639 (unspec:SI [(match_dup 0)
7640 (match_operand:SI 1 "nonimmediate_operand" "r,m")]
7641 UNSPEC_PIC_RESTORE))]
7642 ""
7643 "@
7644 mov\t%0, %1
7645 ldr\t%0, %1"
7646 )
7647
7648 (define_expand "call_internal"
7649 [(parallel [(call (match_operand 0 "memory_operand")
7650 (match_operand 1 "general_operand"))
7651 (use (match_operand 2 "" ""))
7652 (clobber (reg:SI LR_REGNUM))])])
7653
7654 (define_expand "nonsecure_call_internal"
7655 [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
7656 UNSPEC_NONSECURE_MEM)
7657 (match_operand 1 "general_operand"))
7658 (use (match_operand 2 "" ""))
7659 (clobber (reg:SI LR_REGNUM))])]
7660 "use_cmse"
7661 "
7662 {
7663 rtx tmp;
7664 tmp = copy_to_suggested_reg (XEXP (operands[0], 0),
7665 gen_rtx_REG (SImode, R4_REGNUM),
7666 SImode);
7667
7668 operands[0] = replace_equiv_address (operands[0], tmp);
7669 }")
7670
7671 (define_insn "*call_reg_armv5"
7672 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7673 (match_operand 1 "" ""))
7674 (use (match_operand 2 "" ""))
7675 (clobber (reg:SI LR_REGNUM))]
7676 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
7677 "blx%?\\t%0"
7678 [(set_attr "type" "call")]
7679 )
7680
7681 (define_insn "*call_reg_arm"
7682 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7683 (match_operand 1 "" ""))
7684 (use (match_operand 2 "" ""))
7685 (clobber (reg:SI LR_REGNUM))]
7686 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
7687 "*
7688 return output_call (operands);
7689 "
7690 ;; length is worst case, normally it is only two
7691 [(set_attr "length" "12")
7692 (set_attr "type" "call")]
7693 )
7694
7695
7696 (define_expand "call_value"
7697 [(parallel [(set (match_operand 0 "" "")
7698 (call (match_operand 1 "memory_operand")
7699 (match_operand 2 "general_operand")))
7700 (use (match_operand 3 "" ""))
7701 (clobber (reg:SI LR_REGNUM))])]
7702 "TARGET_EITHER"
7703 "
7704 {
7705 rtx pat, callee;
7706 tree addr = MEM_EXPR (operands[1]);
7707
7708 /* In an untyped call, we can get NULL for operand 2. */
7709 if (operands[3] == 0)
7710 operands[3] = const0_rtx;
7711
7712 /* Decide if we should generate indirect calls by loading the
7713 32-bit address of the callee into a register before performing the
7714 branch and link. */
7715 callee = XEXP (operands[1], 0);
7716 if (GET_CODE (callee) == SYMBOL_REF
7717 ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7718 : !REG_P (callee))
7719 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7720
7721 if (TARGET_FDPIC && !SYMBOL_REF_P (XEXP (operands[1], 0)))
7722 /* Indirect call: set r9 with FDPIC value of callee. */
7723 XEXP (operands[1], 0)
7724 = arm_load_function_descriptor (XEXP (operands[1], 0));
7725
7726 if (detect_cmse_nonsecure_call (addr))
7727 {
7728 pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
7729 operands[2], operands[3]);
7730 emit_call_insn (pat);
7731 }
7732 else
7733 {
7734 pat = gen_call_value_internal (operands[0], operands[1],
7735 operands[2], operands[3]);
7736 arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
7737 }
7738
7739 /* Restore FDPIC register (r9) after call. */
7740 if (TARGET_FDPIC)
7741 {
7742 rtx fdpic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
7743 rtx initial_fdpic_reg
7744 = get_hard_reg_initial_val (Pmode, FDPIC_REGNUM);
7745
7746 emit_insn (gen_restore_pic_register_after_call (fdpic_reg,
7747 initial_fdpic_reg));
7748 }
7749
7750 DONE;
7751 }"
7752 )
7753
7754 (define_expand "call_value_internal"
7755 [(parallel [(set (match_operand 0 "" "")
7756 (call (match_operand 1 "memory_operand")
7757 (match_operand 2 "general_operand")))
7758 (use (match_operand 3 "" ""))
7759 (clobber (reg:SI LR_REGNUM))])])
7760
7761 (define_expand "nonsecure_call_value_internal"
7762 [(parallel [(set (match_operand 0 "" "")
7763 (call (unspec:SI [(match_operand 1 "memory_operand")]
7764 UNSPEC_NONSECURE_MEM)
7765 (match_operand 2 "general_operand")))
7766 (use (match_operand 3 "" ""))
7767 (clobber (reg:SI LR_REGNUM))])]
7768 "use_cmse"
7769 "
7770 {
7771 rtx tmp;
7772 tmp = copy_to_suggested_reg (XEXP (operands[1], 0),
7773 gen_rtx_REG (SImode, R4_REGNUM),
7774 SImode);
7775
7776 operands[1] = replace_equiv_address (operands[1], tmp);
7777 }")
7778
7779 (define_insn "*call_value_reg_armv5"
7780 [(set (match_operand 0 "" "")
7781 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7782 (match_operand 2 "" "")))
7783 (use (match_operand 3 "" ""))
7784 (clobber (reg:SI LR_REGNUM))]
7785 "TARGET_ARM && arm_arch5t && !SIBLING_CALL_P (insn)"
7786 "blx%?\\t%1"
7787 [(set_attr "type" "call")]
7788 )
7789
7790 (define_insn "*call_value_reg_arm"
7791 [(set (match_operand 0 "" "")
7792 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7793 (match_operand 2 "" "")))
7794 (use (match_operand 3 "" ""))
7795 (clobber (reg:SI LR_REGNUM))]
7796 "TARGET_ARM && !arm_arch5t && !SIBLING_CALL_P (insn)"
7797 "*
7798 return output_call (&operands[1]);
7799 "
7800 [(set_attr "length" "12")
7801 (set_attr "type" "call")]
7802 )
7803
7804 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7805 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7806
7807 (define_insn "*call_symbol"
7808 [(call (mem:SI (match_operand:SI 0 "" ""))
7809 (match_operand 1 "" ""))
7810 (use (match_operand 2 "" ""))
7811 (clobber (reg:SI LR_REGNUM))]
7812 "TARGET_32BIT
7813 && !SIBLING_CALL_P (insn)
7814 && (GET_CODE (operands[0]) == SYMBOL_REF)
7815 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
7816 "*
7817 {
7818 rtx op = operands[0];
7819
7820 /* Switch mode now when possible. */
7821 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7822 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7823 return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
7824
7825 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7826 }"
7827 [(set_attr "type" "call")]
7828 )
7829
7830 (define_insn "*call_value_symbol"
7831 [(set (match_operand 0 "" "")
7832 (call (mem:SI (match_operand:SI 1 "" ""))
7833 (match_operand:SI 2 "" "")))
7834 (use (match_operand 3 "" ""))
7835 (clobber (reg:SI LR_REGNUM))]
7836 "TARGET_32BIT
7837 && !SIBLING_CALL_P (insn)
7838 && (GET_CODE (operands[1]) == SYMBOL_REF)
7839 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
7840 "*
7841 {
7842 rtx op = operands[1];
7843
7844 /* Switch mode now when possible. */
7845 if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
7846 && arm_arch5t && arm_change_mode_p (SYMBOL_REF_DECL (op)))
7847 return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
7848
7849 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7850 }"
7851 [(set_attr "type" "call")]
7852 )
7853
7854 (define_expand "sibcall_internal"
7855 [(parallel [(call (match_operand 0 "memory_operand")
7856 (match_operand 1 "general_operand"))
7857 (return)
7858 (use (match_operand 2 "" ""))])])
7859
7860 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7861 (define_expand "sibcall"
7862 [(parallel [(call (match_operand 0 "memory_operand")
7863 (match_operand 1 "general_operand"))
7864 (return)
7865 (use (match_operand 2 "" ""))])]
7866 "TARGET_32BIT"
7867 "
7868 {
7869 rtx pat;
7870
7871 if ((!REG_P (XEXP (operands[0], 0))
7872 && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7873 || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7874 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
7875 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7876
7877 if (operands[2] == NULL_RTX)
7878 operands[2] = const0_rtx;
7879
7880 pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7881 arm_emit_call_insn (pat, operands[0], true);
7882 DONE;
7883 }"
7884 )
7885
7886 (define_expand "sibcall_value_internal"
7887 [(parallel [(set (match_operand 0 "" "")
7888 (call (match_operand 1 "memory_operand")
7889 (match_operand 2 "general_operand")))
7890 (return)
7891 (use (match_operand 3 "" ""))])])
7892
7893 (define_expand "sibcall_value"
7894 [(parallel [(set (match_operand 0 "" "")
7895 (call (match_operand 1 "memory_operand")
7896 (match_operand 2 "general_operand")))
7897 (return)
7898 (use (match_operand 3 "" ""))])]
7899 "TARGET_32BIT"
7900 "
7901 {
7902 rtx pat;
7903
7904 if ((!REG_P (XEXP (operands[1], 0))
7905 && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7906 || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7907 && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
7908 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7909
7910 if (operands[3] == NULL_RTX)
7911 operands[3] = const0_rtx;
7912
7913 pat = gen_sibcall_value_internal (operands[0], operands[1],
7914 operands[2], operands[3]);
7915 arm_emit_call_insn (pat, operands[1], true);
7916 DONE;
7917 }"
7918 )
7919
7920 (define_insn "*sibcall_insn"
7921 [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
7922 (match_operand 1 "" ""))
7923 (return)
7924 (use (match_operand 2 "" ""))]
7925 "TARGET_32BIT && SIBLING_CALL_P (insn)"
7926 "*
7927 if (which_alternative == 1)
7928 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7929 else
7930 {
7931 if (arm_arch5t || arm_arch4t)
7932 return \"bx%?\\t%0\\t%@ indirect register sibling call\";
7933 else
7934 return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7935 }
7936 "
7937 [(set_attr "type" "call")]
7938 )
7939
7940 (define_insn "*sibcall_value_insn"
7941 [(set (match_operand 0 "" "")
7942 (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
7943 (match_operand 2 "" "")))
7944 (return)
7945 (use (match_operand 3 "" ""))]
7946 "TARGET_32BIT && SIBLING_CALL_P (insn)"
7947 "*
7948 if (which_alternative == 1)
7949 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7950 else
7951 {
7952 if (arm_arch5t || arm_arch4t)
7953 return \"bx%?\\t%1\";
7954 else
7955 return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7956 }
7957 "
7958 [(set_attr "type" "call")]
7959 )
7960
7961 (define_expand "<return_str>return"
7962 [(RETURNS)]
7963 "(TARGET_ARM || (TARGET_THUMB2
7964 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7965 && !IS_STACKALIGN (arm_current_func_type ())))
7966 <return_cond_false>"
7967 "
7968 {
7969 if (TARGET_THUMB2)
7970 {
7971 thumb2_expand_return (<return_simple_p>);
7972 DONE;
7973 }
7974 }
7975 "
7976 )
7977
7978 ;; Often the return insn will be the same as loading from memory, so set attr
7979 (define_insn "*arm_return"
7980 [(return)]
7981 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7982 "*
7983 {
7984 if (arm_ccfsm_state == 2)
7985 {
7986 arm_ccfsm_state += 2;
7987 return \"\";
7988 }
7989 return output_return_instruction (const_true_rtx, true, false, false);
7990 }"
7991 [(set_attr "type" "load_4")
7992 (set_attr "length" "12")
7993 (set_attr "predicable" "yes")]
7994 )
7995
7996 (define_insn "*cond_<return_str>return"
7997 [(set (pc)
7998 (if_then_else (match_operator 0 "arm_comparison_operator"
7999 [(match_operand 1 "cc_register" "") (const_int 0)])
8000 (RETURNS)
8001 (pc)))]
8002 "TARGET_ARM <return_cond_true>"
8003 "*
8004 {
8005 if (arm_ccfsm_state == 2)
8006 {
8007 arm_ccfsm_state += 2;
8008 return \"\";
8009 }
8010 return output_return_instruction (operands[0], true, false,
8011 <return_simple_p>);
8012 }"
8013 [(set_attr "conds" "use")
8014 (set_attr "length" "12")
8015 (set_attr "type" "load_4")]
8016 )
8017
8018 (define_insn "*cond_<return_str>return_inverted"
8019 [(set (pc)
8020 (if_then_else (match_operator 0 "arm_comparison_operator"
8021 [(match_operand 1 "cc_register" "") (const_int 0)])
8022 (pc)
8023 (RETURNS)))]
8024 "TARGET_ARM <return_cond_true>"
8025 "*
8026 {
8027 if (arm_ccfsm_state == 2)
8028 {
8029 arm_ccfsm_state += 2;
8030 return \"\";
8031 }
8032 return output_return_instruction (operands[0], true, true,
8033 <return_simple_p>);
8034 }"
8035 [(set_attr "conds" "use")
8036 (set_attr "length" "12")
8037 (set_attr "type" "load_4")]
8038 )
8039
8040 (define_insn "*arm_simple_return"
8041 [(simple_return)]
8042 "TARGET_ARM"
8043 "*
8044 {
8045 if (arm_ccfsm_state == 2)
8046 {
8047 arm_ccfsm_state += 2;
8048 return \"\";
8049 }
8050 return output_return_instruction (const_true_rtx, true, false, true);
8051 }"
8052 [(set_attr "type" "branch")
8053 (set_attr "length" "4")
8054 (set_attr "predicable" "yes")]
8055 )
8056
8057 ;; Generate a sequence of instructions to determine if the processor is
8058 ;; in 26-bit or 32-bit mode, and return the appropriate return address
8059 ;; mask.
8060
8061 (define_expand "return_addr_mask"
8062 [(set (match_dup 1)
8063 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8064 (const_int 0)))
8065 (set (match_operand:SI 0 "s_register_operand")
8066 (if_then_else:SI (eq (match_dup 1) (const_int 0))
8067 (const_int -1)
8068 (const_int 67108860)))] ; 0x03fffffc
8069 "TARGET_ARM"
8070 "
8071 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8072 ")
8073
8074 (define_insn "*check_arch2"
8075 [(set (match_operand:CC_NOOV 0 "cc_register" "")
8076 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8077 (const_int 0)))]
8078 "TARGET_ARM"
8079 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8080 [(set_attr "length" "8")
8081 (set_attr "conds" "set")
8082 (set_attr "type" "multiple")]
8083 )
8084
8085 ;; Call subroutine returning any type.
8086
8087 (define_expand "untyped_call"
8088 [(parallel [(call (match_operand 0 "" "")
8089 (const_int 0))
8090 (match_operand 1 "" "")
8091 (match_operand 2 "" "")])]
8092 "TARGET_EITHER && !TARGET_FDPIC"
8093 "
8094 {
8095 int i;
8096 rtx par = gen_rtx_PARALLEL (VOIDmode,
8097 rtvec_alloc (XVECLEN (operands[2], 0)));
8098 rtx addr = gen_reg_rtx (Pmode);
8099 rtx mem;
8100 int size = 0;
8101
8102 emit_move_insn (addr, XEXP (operands[1], 0));
8103 mem = change_address (operands[1], BLKmode, addr);
8104
8105 for (i = 0; i < XVECLEN (operands[2], 0); i++)
8106 {
8107 rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8108
8109 /* Default code only uses r0 as a return value, but we could
8110 be using anything up to 4 registers. */
8111 if (REGNO (src) == R0_REGNUM)
8112 src = gen_rtx_REG (TImode, R0_REGNUM);
8113
8114 XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8115 GEN_INT (size));
8116 size += GET_MODE_SIZE (GET_MODE (src));
8117 }
8118
8119 emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
8120
8121 size = 0;
8122
8123 for (i = 0; i < XVECLEN (par, 0); i++)
8124 {
8125 HOST_WIDE_INT offset = 0;
8126 rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8127
8128 if (size != 0)
8129 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8130
8131 mem = change_address (mem, GET_MODE (reg), NULL);
8132 if (REGNO (reg) == R0_REGNUM)
8133 {
8134 /* On thumb we have to use a write-back instruction. */
8135 emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8136 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8137 size = TARGET_ARM ? 16 : 0;
8138 }
8139 else
8140 {
8141 emit_move_insn (mem, reg);
8142 size = GET_MODE_SIZE (GET_MODE (reg));
8143 }
8144 }
8145
8146 /* The optimizer does not know that the call sets the function value
8147 registers we stored in the result block. We avoid problems by
8148 claiming that all hard registers are used and clobbered at this
8149 point. */
8150 emit_insn (gen_blockage ());
8151
8152 DONE;
8153 }"
8154 )
8155
8156 (define_expand "untyped_return"
8157 [(match_operand:BLK 0 "memory_operand")
8158 (match_operand 1 "" "")]
8159 "TARGET_EITHER && !TARGET_FDPIC"
8160 "
8161 {
8162 int i;
8163 rtx addr = gen_reg_rtx (Pmode);
8164 rtx mem;
8165 int size = 0;
8166
8167 emit_move_insn (addr, XEXP (operands[0], 0));
8168 mem = change_address (operands[0], BLKmode, addr);
8169
8170 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8171 {
8172 HOST_WIDE_INT offset = 0;
8173 rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8174
8175 if (size != 0)
8176 emit_move_insn (addr, plus_constant (Pmode, addr, size));
8177
8178 mem = change_address (mem, GET_MODE (reg), NULL);
8179 if (REGNO (reg) == R0_REGNUM)
8180 {
8181 /* On thumb we have to use a write-back instruction. */
8182 emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8183 TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8184 size = TARGET_ARM ? 16 : 0;
8185 }
8186 else
8187 {
8188 emit_move_insn (reg, mem);
8189 size = GET_MODE_SIZE (GET_MODE (reg));
8190 }
8191 }
8192
8193 /* Emit USE insns before the return. */
8194 for (i = 0; i < XVECLEN (operands[1], 0); i++)
8195 emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8196
8197 /* Construct the return. */
8198 expand_naked_return ();
8199
8200 DONE;
8201 }"
8202 )
8203
8204 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8205 ;; all of memory. This blocks insns from being moved across this point.
8206
8207 (define_insn "blockage"
8208 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8209 "TARGET_EITHER"
8210 ""
8211 [(set_attr "length" "0")
8212 (set_attr "type" "block")]
8213 )
8214
8215 ;; Since we hard code r0 here use the 'o' constraint to prevent
8216 ;; provoking undefined behaviour in the hardware with putting out
8217 ;; auto-increment operations with potentially r0 as the base register.
8218 (define_insn "probe_stack"
8219 [(set (match_operand:SI 0 "memory_operand" "=o")
8220 (unspec:SI [(const_int 0)] UNSPEC_PROBE_STACK))]
8221 "TARGET_32BIT"
8222 "str%?\\tr0, %0"
8223 [(set_attr "type" "store_4")
8224 (set_attr "predicable" "yes")]
8225 )
8226
8227 (define_insn "probe_stack_range"
8228 [(set (match_operand:SI 0 "register_operand" "=r")
8229 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
8230 (match_operand:SI 2 "register_operand" "r")]
8231 VUNSPEC_PROBE_STACK_RANGE))]
8232 "TARGET_32BIT"
8233 {
8234 return output_probe_stack_range (operands[0], operands[2]);
8235 }
8236 [(set_attr "type" "multiple")
8237 (set_attr "conds" "clob")]
8238 )
8239
8240 ;; Named patterns for stack smashing protection.
8241 (define_expand "stack_protect_combined_set"
8242 [(parallel
8243 [(set (match_operand:SI 0 "memory_operand")
8244 (unspec:SI [(match_operand:SI 1 "guard_operand")]
8245 UNSPEC_SP_SET))
8246 (clobber (match_scratch:SI 2 ""))
8247 (clobber (match_scratch:SI 3 ""))])]
8248 ""
8249 ""
8250 )
8251
8252 ;; Use a separate insn from the above expand to be able to have the mem outside
8253 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8254 ;; try to reload the guard since we need to control how PIC access is done in
8255 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8256 ;; legitimize_pic_address ()).
8257 (define_insn_and_split "*stack_protect_combined_set_insn"
8258 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8259 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8260 UNSPEC_SP_SET))
8261 (clobber (match_scratch:SI 2 "=&l,&r"))
8262 (clobber (match_scratch:SI 3 "=&l,&r"))]
8263 ""
8264 "#"
8265 "reload_completed"
8266 [(parallel [(set (match_dup 0) (unspec:SI [(mem:SI (match_dup 2))]
8267 UNSPEC_SP_SET))
8268 (clobber (match_dup 2))])]
8269 "
8270 {
8271 if (flag_pic)
8272 {
8273 rtx pic_reg;
8274
8275 if (TARGET_FDPIC)
8276 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8277 else
8278 pic_reg = operands[3];
8279
8280 /* Forces recomputing of GOT base now. */
8281 legitimize_pic_address (operands[1], SImode, operands[2], pic_reg,
8282 true /*compute_now*/);
8283 }
8284 else
8285 {
8286 if (address_operand (operands[1], SImode))
8287 operands[2] = operands[1];
8288 else
8289 {
8290 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8291 emit_move_insn (operands[2], mem);
8292 }
8293 }
8294 }"
8295 [(set_attr "arch" "t1,32")]
8296 )
8297
8298 ;; DO NOT SPLIT THIS INSN. It's important for security reasons that the
8299 ;; canary value does not live beyond the life of this sequence.
8300 (define_insn "*stack_protect_set_insn"
8301 [(set (match_operand:SI 0 "memory_operand" "=m,m")
8302 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "+&l,&r"))]
8303 UNSPEC_SP_SET))
8304 (clobber (match_dup 1))]
8305 ""
8306 "@
8307 ldr\\t%1, [%1]\;str\\t%1, %0\;movs\t%1, #0
8308 ldr\\t%1, [%1]\;str\\t%1, %0\;mov\t%1, #0"
8309 [(set_attr "length" "8,12")
8310 (set_attr "conds" "clob,nocond")
8311 (set_attr "type" "multiple")
8312 (set_attr "arch" "t1,32")]
8313 )
8314
8315 (define_expand "stack_protect_combined_test"
8316 [(parallel
8317 [(set (pc)
8318 (if_then_else
8319 (eq (match_operand:SI 0 "memory_operand")
8320 (unspec:SI [(match_operand:SI 1 "guard_operand")]
8321 UNSPEC_SP_TEST))
8322 (label_ref (match_operand 2))
8323 (pc)))
8324 (clobber (match_scratch:SI 3 ""))
8325 (clobber (match_scratch:SI 4 ""))
8326 (clobber (reg:CC CC_REGNUM))])]
8327 ""
8328 ""
8329 )
8330
8331 ;; Use a separate insn from the above expand to be able to have the mem outside
8332 ;; the operand #1 when register allocation comes. This is needed to avoid LRA
8333 ;; try to reload the guard since we need to control how PIC access is done in
8334 ;; the -fpic/-fPIC case (see COMPUTE_NOW parameter when calling
8335 ;; legitimize_pic_address ()).
8336 (define_insn_and_split "*stack_protect_combined_test_insn"
8337 [(set (pc)
8338 (if_then_else
8339 (eq (match_operand:SI 0 "memory_operand" "m,m")
8340 (unspec:SI [(mem:SI (match_operand:SI 1 "guard_addr_operand" "X,X"))]
8341 UNSPEC_SP_TEST))
8342 (label_ref (match_operand 2))
8343 (pc)))
8344 (clobber (match_scratch:SI 3 "=&l,&r"))
8345 (clobber (match_scratch:SI 4 "=&l,&r"))
8346 (clobber (reg:CC CC_REGNUM))]
8347 ""
8348 "#"
8349 "reload_completed"
8350 [(const_int 0)]
8351 {
8352 rtx eq;
8353
8354 if (flag_pic)
8355 {
8356 rtx pic_reg;
8357
8358 if (TARGET_FDPIC)
8359 pic_reg = gen_rtx_REG (Pmode, FDPIC_REGNUM);
8360 else
8361 pic_reg = operands[4];
8362
8363 /* Forces recomputing of GOT base now. */
8364 legitimize_pic_address (operands[1], SImode, operands[3], pic_reg,
8365 true /*compute_now*/);
8366 }
8367 else
8368 {
8369 if (address_operand (operands[1], SImode))
8370 operands[3] = operands[1];
8371 else
8372 {
8373 rtx mem = XEXP (force_const_mem (SImode, operands[1]), 0);
8374 emit_move_insn (operands[3], mem);
8375 }
8376 }
8377 if (TARGET_32BIT)
8378 {
8379 emit_insn (gen_arm_stack_protect_test_insn (operands[4], operands[0],
8380 operands[3]));
8381 rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM);
8382 eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx);
8383 emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg));
8384 }
8385 else
8386 {
8387 emit_insn (gen_thumb1_stack_protect_test_insn (operands[4], operands[0],
8388 operands[3]));
8389 eq = gen_rtx_EQ (VOIDmode, operands[4], const0_rtx);
8390 emit_jump_insn (gen_cbranchsi4 (eq, operands[4], const0_rtx,
8391 operands[2]));
8392 }
8393 DONE;
8394 }
8395 [(set_attr "arch" "t1,32")]
8396 )
8397
8398 (define_insn "arm_stack_protect_test_insn"
8399 [(set (reg:CC_Z CC_REGNUM)
8400 (compare:CC_Z (unspec:SI [(match_operand:SI 1 "memory_operand" "m,m")
8401 (mem:SI (match_operand:SI 2 "register_operand" "+l,r"))]
8402 UNSPEC_SP_TEST)
8403 (const_int 0)))
8404 (clobber (match_operand:SI 0 "register_operand" "=&l,&r"))
8405 (clobber (match_dup 2))]
8406 "TARGET_32BIT"
8407 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0"
8408 [(set_attr "length" "8,12")
8409 (set_attr "conds" "set")
8410 (set_attr "type" "multiple")
8411 (set_attr "arch" "t,32")]
8412 )
8413
8414 (define_expand "casesi"
8415 [(match_operand:SI 0 "s_register_operand") ; index to jump on
8416 (match_operand:SI 1 "const_int_operand") ; lower bound
8417 (match_operand:SI 2 "const_int_operand") ; total range
8418 (match_operand:SI 3 "" "") ; table label
8419 (match_operand:SI 4 "" "")] ; Out of range label
8420 "(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
8421 "
8422 {
8423 enum insn_code code;
8424 if (operands[1] != const0_rtx)
8425 {
8426 rtx reg = gen_reg_rtx (SImode);
8427
8428 emit_insn (gen_addsi3 (reg, operands[0],
8429 gen_int_mode (-INTVAL (operands[1]),
8430 SImode)));
8431 operands[0] = reg;
8432 }
8433
8434 if (TARGET_ARM)
8435 code = CODE_FOR_arm_casesi_internal;
8436 else if (TARGET_THUMB1)
8437 code = CODE_FOR_thumb1_casesi_internal_pic;
8438 else if (flag_pic)
8439 code = CODE_FOR_thumb2_casesi_internal_pic;
8440 else
8441 code = CODE_FOR_thumb2_casesi_internal;
8442
8443 if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8444 operands[2] = force_reg (SImode, operands[2]);
8445
8446 emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8447 operands[3], operands[4]));
8448 DONE;
8449 }"
8450 )
8451
8452 ;; The USE in this pattern is needed to tell flow analysis that this is
8453 ;; a CASESI insn. It has no other purpose.
8454 (define_expand "arm_casesi_internal"
8455 [(parallel [(set (pc)
8456 (if_then_else
8457 (leu (match_operand:SI 0 "s_register_operand")
8458 (match_operand:SI 1 "arm_rhs_operand"))
8459 (match_dup 4)
8460 (label_ref:SI (match_operand 3 ""))))
8461 (clobber (reg:CC CC_REGNUM))
8462 (use (label_ref:SI (match_operand 2 "")))])]
8463 "TARGET_ARM"
8464 {
8465 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
8466 operands[4] = gen_rtx_PLUS (SImode, operands[4],
8467 gen_rtx_LABEL_REF (SImode, operands[2]));
8468 operands[4] = gen_rtx_MEM (SImode, operands[4]);
8469 MEM_READONLY_P (operands[4]) = 1;
8470 MEM_NOTRAP_P (operands[4]) = 1;
8471 })
8472
8473 (define_insn "*arm_casesi_internal"
8474 [(parallel [(set (pc)
8475 (if_then_else
8476 (leu (match_operand:SI 0 "s_register_operand" "r")
8477 (match_operand:SI 1 "arm_rhs_operand" "rI"))
8478 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8479 (label_ref:SI (match_operand 2 "" ""))))
8480 (label_ref:SI (match_operand 3 "" ""))))
8481 (clobber (reg:CC CC_REGNUM))
8482 (use (label_ref:SI (match_dup 2)))])]
8483 "TARGET_ARM"
8484 "*
8485 if (flag_pic)
8486 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8487 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8488 "
8489 [(set_attr "conds" "clob")
8490 (set_attr "length" "12")
8491 (set_attr "type" "multiple")]
8492 )
8493
8494 (define_expand "indirect_jump"
8495 [(set (pc)
8496 (match_operand:SI 0 "s_register_operand"))]
8497 "TARGET_EITHER"
8498 "
8499 /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8500 address and use bx. */
8501 if (TARGET_THUMB2)
8502 {
8503 rtx tmp;
8504 tmp = gen_reg_rtx (SImode);
8505 emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8506 operands[0] = tmp;
8507 }
8508 "
8509 )
8510
8511 ;; NB Never uses BX.
8512 (define_insn "*arm_indirect_jump"
8513 [(set (pc)
8514 (match_operand:SI 0 "s_register_operand" "r"))]
8515 "TARGET_ARM"
8516 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8517 [(set_attr "predicable" "yes")
8518 (set_attr "type" "branch")]
8519 )
8520
8521 (define_insn "*load_indirect_jump"
8522 [(set (pc)
8523 (match_operand:SI 0 "memory_operand" "m"))]
8524 "TARGET_ARM"
8525 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8526 [(set_attr "type" "load_4")
8527 (set_attr "pool_range" "4096")
8528 (set_attr "neg_pool_range" "4084")
8529 (set_attr "predicable" "yes")]
8530 )
8531
8532 \f
8533 ;; Misc insns
8534
8535 (define_insn "nop"
8536 [(const_int 0)]
8537 "TARGET_EITHER"
8538 "nop"
8539 [(set (attr "length")
8540 (if_then_else (eq_attr "is_thumb" "yes")
8541 (const_int 2)
8542 (const_int 4)))
8543 (set_attr "type" "mov_reg")]
8544 )
8545
8546 (define_insn "trap"
8547 [(trap_if (const_int 1) (const_int 0))]
8548 ""
8549 "*
8550 if (TARGET_ARM)
8551 return \".inst\\t0xe7f000f0\";
8552 else
8553 return \".inst\\t0xdeff\";
8554 "
8555 [(set (attr "length")
8556 (if_then_else (eq_attr "is_thumb" "yes")
8557 (const_int 2)
8558 (const_int 4)))
8559 (set_attr "type" "trap")
8560 (set_attr "conds" "unconditional")]
8561 )
8562
8563 \f
8564 ;; Patterns to allow combination of arithmetic, cond code and shifts
8565
8566 (define_insn "*<arith_shift_insn>_multsi"
8567 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8568 (SHIFTABLE_OPS:SI
8569 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8570 (match_operand:SI 3 "power_of_two_operand" ""))
8571 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
8572 "TARGET_32BIT"
8573 "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8574 [(set_attr "predicable" "yes")
8575 (set_attr "shift" "2")
8576 (set_attr "arch" "a,t2")
8577 (set_attr "type" "alu_shift_imm")])
8578
8579 (define_insn "*<arith_shift_insn>_shiftsi"
8580 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8581 (SHIFTABLE_OPS:SI
8582 (match_operator:SI 2 "shift_nomul_operator"
8583 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8584 (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8585 (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
8586 "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
8587 "<arith_shift_insn>%?\\t%0, %1, %3%S2"
8588 [(set_attr "predicable" "yes")
8589 (set_attr "shift" "3")
8590 (set_attr "arch" "a,t2,a")
8591 (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
8592
8593 (define_split
8594 [(set (match_operand:SI 0 "s_register_operand" "")
8595 (match_operator:SI 1 "shiftable_operator"
8596 [(match_operator:SI 2 "shiftable_operator"
8597 [(match_operator:SI 3 "shift_operator"
8598 [(match_operand:SI 4 "s_register_operand" "")
8599 (match_operand:SI 5 "reg_or_int_operand" "")])
8600 (match_operand:SI 6 "s_register_operand" "")])
8601 (match_operand:SI 7 "arm_rhs_operand" "")]))
8602 (clobber (match_operand:SI 8 "s_register_operand" ""))]
8603 "TARGET_32BIT"
8604 [(set (match_dup 8)
8605 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8606 (match_dup 6)]))
8607 (set (match_dup 0)
8608 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8609 "")
8610
8611 (define_insn "*arith_shiftsi_compare0"
8612 [(set (reg:CC_NOOV CC_REGNUM)
8613 (compare:CC_NOOV
8614 (match_operator:SI 1 "shiftable_operator"
8615 [(match_operator:SI 3 "shift_operator"
8616 [(match_operand:SI 4 "s_register_operand" "r,r")
8617 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8618 (match_operand:SI 2 "s_register_operand" "r,r")])
8619 (const_int 0)))
8620 (set (match_operand:SI 0 "s_register_operand" "=r,r")
8621 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8622 (match_dup 2)]))]
8623 "TARGET_32BIT"
8624 "%i1s%?\\t%0, %2, %4%S3"
8625 [(set_attr "conds" "set")
8626 (set_attr "shift" "4")
8627 (set_attr "arch" "32,a")
8628 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8629
8630 (define_insn "*arith_shiftsi_compare0_scratch"
8631 [(set (reg:CC_NOOV CC_REGNUM)
8632 (compare:CC_NOOV
8633 (match_operator:SI 1 "shiftable_operator"
8634 [(match_operator:SI 3 "shift_operator"
8635 [(match_operand:SI 4 "s_register_operand" "r,r")
8636 (match_operand:SI 5 "shift_amount_operand" "M,r")])
8637 (match_operand:SI 2 "s_register_operand" "r,r")])
8638 (const_int 0)))
8639 (clobber (match_scratch:SI 0 "=r,r"))]
8640 "TARGET_32BIT"
8641 "%i1s%?\\t%0, %2, %4%S3"
8642 [(set_attr "conds" "set")
8643 (set_attr "shift" "4")
8644 (set_attr "arch" "32,a")
8645 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8646
8647 (define_insn "*sub_shiftsi"
8648 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8649 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
8650 (match_operator:SI 2 "shift_operator"
8651 [(match_operand:SI 3 "s_register_operand" "r,r")
8652 (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8653 "TARGET_32BIT"
8654 "sub%?\\t%0, %1, %3%S2"
8655 [(set_attr "predicable" "yes")
8656 (set_attr "predicable_short_it" "no")
8657 (set_attr "shift" "3")
8658 (set_attr "arch" "32,a")
8659 (set_attr "type" "alus_shift_imm,alus_shift_reg")])
8660
8661 (define_insn "*sub_shiftsi_compare0"
8662 [(set (reg:CC_NOOV CC_REGNUM)
8663 (compare:CC_NOOV
8664 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8665 (match_operator:SI 2 "shift_operator"
8666 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8667 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8668 (const_int 0)))
8669 (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8670 (minus:SI (match_dup 1)
8671 (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8672 "TARGET_32BIT"
8673 "subs%?\\t%0, %1, %3%S2"
8674 [(set_attr "conds" "set")
8675 (set_attr "shift" "3")
8676 (set_attr "arch" "32,a,a")
8677 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8678
8679 (define_insn "*sub_shiftsi_compare0_scratch"
8680 [(set (reg:CC_NOOV CC_REGNUM)
8681 (compare:CC_NOOV
8682 (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
8683 (match_operator:SI 2 "shift_operator"
8684 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8685 (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
8686 (const_int 0)))
8687 (clobber (match_scratch:SI 0 "=r,r,r"))]
8688 "TARGET_32BIT"
8689 "subs%?\\t%0, %1, %3%S2"
8690 [(set_attr "conds" "set")
8691 (set_attr "shift" "3")
8692 (set_attr "arch" "32,a,a")
8693 (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
8694 \f
8695
8696 (define_insn_and_split "*and_scc"
8697 [(set (match_operand:SI 0 "s_register_operand" "=r")
8698 (and:SI (match_operator:SI 1 "arm_comparison_operator"
8699 [(match_operand 2 "cc_register" "") (const_int 0)])
8700 (match_operand:SI 3 "s_register_operand" "r")))]
8701 "TARGET_ARM"
8702 "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8703 "&& reload_completed"
8704 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8705 (cond_exec (match_dup 4) (set (match_dup 0)
8706 (and:SI (match_dup 3) (const_int 1))))]
8707 {
8708 machine_mode mode = GET_MODE (operands[2]);
8709 enum rtx_code rc = GET_CODE (operands[1]);
8710
8711 /* Note that operands[4] is the same as operands[1],
8712 but with VOIDmode as the result. */
8713 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8714 if (mode == CCFPmode || mode == CCFPEmode)
8715 rc = reverse_condition_maybe_unordered (rc);
8716 else
8717 rc = reverse_condition (rc);
8718 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8719 }
8720 [(set_attr "conds" "use")
8721 (set_attr "type" "multiple")
8722 (set_attr "length" "8")]
8723 )
8724
8725 (define_insn_and_split "*ior_scc"
8726 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8727 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8728 [(match_operand 2 "cc_register" "") (const_int 0)])
8729 (match_operand:SI 3 "s_register_operand" "0,?r")))]
8730 "TARGET_ARM"
8731 "@
8732 orr%d1\\t%0, %3, #1
8733 #"
8734 "&& reload_completed
8735 && REGNO (operands [0]) != REGNO (operands[3])"
8736 ;; && which_alternative == 1
8737 ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8738 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8739 (cond_exec (match_dup 4) (set (match_dup 0)
8740 (ior:SI (match_dup 3) (const_int 1))))]
8741 {
8742 machine_mode mode = GET_MODE (operands[2]);
8743 enum rtx_code rc = GET_CODE (operands[1]);
8744
8745 /* Note that operands[4] is the same as operands[1],
8746 but with VOIDmode as the result. */
8747 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8748 if (mode == CCFPmode || mode == CCFPEmode)
8749 rc = reverse_condition_maybe_unordered (rc);
8750 else
8751 rc = reverse_condition (rc);
8752 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8753 }
8754 [(set_attr "conds" "use")
8755 (set_attr "length" "4,8")
8756 (set_attr "type" "logic_imm,multiple")]
8757 )
8758
8759 ; A series of splitters for the compare_scc pattern below. Note that
8760 ; order is important.
8761 (define_split
8762 [(set (match_operand:SI 0 "s_register_operand" "")
8763 (lt:SI (match_operand:SI 1 "s_register_operand" "")
8764 (const_int 0)))
8765 (clobber (reg:CC CC_REGNUM))]
8766 "TARGET_32BIT && reload_completed"
8767 [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8768
8769 (define_split
8770 [(set (match_operand:SI 0 "s_register_operand" "")
8771 (ge:SI (match_operand:SI 1 "s_register_operand" "")
8772 (const_int 0)))
8773 (clobber (reg:CC CC_REGNUM))]
8774 "TARGET_32BIT && reload_completed"
8775 [(set (match_dup 0) (not:SI (match_dup 1)))
8776 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8777
8778 (define_split
8779 [(set (match_operand:SI 0 "s_register_operand" "")
8780 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8781 (const_int 0)))
8782 (clobber (reg:CC CC_REGNUM))]
8783 "arm_arch5t && TARGET_32BIT"
8784 [(set (match_dup 0) (clz:SI (match_dup 1)))
8785 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8786 )
8787
8788 (define_split
8789 [(set (match_operand:SI 0 "s_register_operand" "")
8790 (eq:SI (match_operand:SI 1 "s_register_operand" "")
8791 (const_int 0)))
8792 (clobber (reg:CC CC_REGNUM))]
8793 "TARGET_32BIT && reload_completed"
8794 [(parallel
8795 [(set (reg:CC CC_REGNUM)
8796 (compare:CC (const_int 1) (match_dup 1)))
8797 (set (match_dup 0)
8798 (minus:SI (const_int 1) (match_dup 1)))])
8799 (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
8800 (set (match_dup 0) (const_int 0)))])
8801
8802 (define_split
8803 [(set (match_operand:SI 0 "s_register_operand" "")
8804 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8805 (match_operand:SI 2 "const_int_operand" "")))
8806 (clobber (reg:CC CC_REGNUM))]
8807 "TARGET_32BIT && reload_completed"
8808 [(parallel
8809 [(set (reg:CC CC_REGNUM)
8810 (compare:CC (match_dup 1) (match_dup 2)))
8811 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8812 (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8813 (set (match_dup 0) (const_int 1)))]
8814 {
8815 operands[3] = gen_int_mode (-INTVAL (operands[2]), SImode);
8816 })
8817
8818 (define_split
8819 [(set (match_operand:SI 0 "s_register_operand" "")
8820 (ne:SI (match_operand:SI 1 "s_register_operand" "")
8821 (match_operand:SI 2 "arm_add_operand" "")))
8822 (clobber (reg:CC CC_REGNUM))]
8823 "TARGET_32BIT && reload_completed"
8824 [(parallel
8825 [(set (reg:CC_NOOV CC_REGNUM)
8826 (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8827 (const_int 0)))
8828 (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8829 (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8830 (set (match_dup 0) (const_int 1)))])
8831
8832 (define_insn_and_split "*compare_scc"
8833 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
8834 (match_operator:SI 1 "arm_comparison_operator"
8835 [(match_operand:SI 2 "s_register_operand" "r,r")
8836 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8837 (clobber (reg:CC CC_REGNUM))]
8838 "TARGET_32BIT"
8839 "#"
8840 "&& reload_completed"
8841 [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8842 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8843 (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8844 {
8845 rtx tmp1;
8846 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8847 operands[2], operands[3]);
8848 enum rtx_code rc = GET_CODE (operands[1]);
8849
8850 tmp1 = gen_rtx_REG (mode, CC_REGNUM);
8851
8852 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8853 if (mode == CCFPmode || mode == CCFPEmode)
8854 rc = reverse_condition_maybe_unordered (rc);
8855 else
8856 rc = reverse_condition (rc);
8857 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8858 }
8859 [(set_attr "type" "multiple")]
8860 )
8861
8862 ;; Attempt to improve the sequence generated by the compare_scc splitters
8863 ;; not to use conditional execution.
8864
8865 ;; Rd = (eq (reg1) (const_int0)) // ARMv5
8866 ;; clz Rd, reg1
8867 ;; lsr Rd, Rd, #5
8868 (define_peephole2
8869 [(set (reg:CC CC_REGNUM)
8870 (compare:CC (match_operand:SI 1 "register_operand" "")
8871 (const_int 0)))
8872 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8873 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8874 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8875 (set (match_dup 0) (const_int 1)))]
8876 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8877 [(set (match_dup 0) (clz:SI (match_dup 1)))
8878 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8879 )
8880
8881 ;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8882 ;; negs Rd, reg1
8883 ;; adc Rd, Rd, reg1
8884 (define_peephole2
8885 [(set (reg:CC CC_REGNUM)
8886 (compare:CC (match_operand:SI 1 "register_operand" "")
8887 (const_int 0)))
8888 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8889 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8890 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8891 (set (match_dup 0) (const_int 1)))
8892 (match_scratch:SI 2 "r")]
8893 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8894 [(parallel
8895 [(set (reg:CC CC_REGNUM)
8896 (compare:CC (const_int 0) (match_dup 1)))
8897 (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8898 (set (match_dup 0)
8899 (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8900 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8901 )
8902
8903 ;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
8904 ;; sub Rd, Reg1, reg2
8905 ;; clz Rd, Rd
8906 ;; lsr Rd, Rd, #5
8907 (define_peephole2
8908 [(set (reg:CC CC_REGNUM)
8909 (compare:CC (match_operand:SI 1 "register_operand" "")
8910 (match_operand:SI 2 "arm_rhs_operand" "")))
8911 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8912 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8913 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8914 (set (match_dup 0) (const_int 1)))]
8915 "arm_arch5t && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8916 && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
8917 [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8918 (set (match_dup 0) (clz:SI (match_dup 0)))
8919 (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8920 )
8921
8922
8923 ;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
8924 ;; sub T1, Reg1, reg2
8925 ;; negs Rd, T1
8926 ;; adc Rd, Rd, T1
8927 (define_peephole2
8928 [(set (reg:CC CC_REGNUM)
8929 (compare:CC (match_operand:SI 1 "register_operand" "")
8930 (match_operand:SI 2 "arm_rhs_operand" "")))
8931 (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8932 (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8933 (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8934 (set (match_dup 0) (const_int 1)))
8935 (match_scratch:SI 3 "r")]
8936 "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8937 [(set (match_dup 3) (match_dup 4))
8938 (parallel
8939 [(set (reg:CC CC_REGNUM)
8940 (compare:CC (const_int 0) (match_dup 3)))
8941 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
8942 (set (match_dup 0)
8943 (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8944 (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8945 "
8946 if (CONST_INT_P (operands[2]))
8947 operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8948 else
8949 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8950 ")
8951
8952 (define_insn "*cond_move"
8953 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8954 (if_then_else:SI (match_operator 3 "equality_operator"
8955 [(match_operator 4 "arm_comparison_operator"
8956 [(match_operand 5 "cc_register" "") (const_int 0)])
8957 (const_int 0)])
8958 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8959 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8960 "TARGET_ARM"
8961 "*
8962 if (GET_CODE (operands[3]) == NE)
8963 {
8964 if (which_alternative != 1)
8965 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8966 if (which_alternative != 0)
8967 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8968 return \"\";
8969 }
8970 if (which_alternative != 0)
8971 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8972 if (which_alternative != 1)
8973 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8974 return \"\";
8975 "
8976 [(set_attr "conds" "use")
8977 (set_attr_alternative "type"
8978 [(if_then_else (match_operand 2 "const_int_operand" "")
8979 (const_string "mov_imm")
8980 (const_string "mov_reg"))
8981 (if_then_else (match_operand 1 "const_int_operand" "")
8982 (const_string "mov_imm")
8983 (const_string "mov_reg"))
8984 (const_string "multiple")])
8985 (set_attr "length" "4,4,8")]
8986 )
8987
8988 (define_insn "*cond_arith"
8989 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8990 (match_operator:SI 5 "shiftable_operator"
8991 [(match_operator:SI 4 "arm_comparison_operator"
8992 [(match_operand:SI 2 "s_register_operand" "r,r")
8993 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8994 (match_operand:SI 1 "s_register_operand" "0,?r")]))
8995 (clobber (reg:CC CC_REGNUM))]
8996 "TARGET_ARM"
8997 "*
8998 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8999 return \"%i5\\t%0, %1, %2, lsr #31\";
9000
9001 output_asm_insn (\"cmp\\t%2, %3\", operands);
9002 if (GET_CODE (operands[5]) == AND)
9003 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9004 else if (GET_CODE (operands[5]) == MINUS)
9005 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9006 else if (which_alternative != 0)
9007 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9008 return \"%i5%d4\\t%0, %1, #1\";
9009 "
9010 [(set_attr "conds" "clob")
9011 (set_attr "length" "12")
9012 (set_attr "type" "multiple")]
9013 )
9014
9015 (define_insn "*cond_sub"
9016 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9017 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9018 (match_operator:SI 4 "arm_comparison_operator"
9019 [(match_operand:SI 2 "s_register_operand" "r,r")
9020 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9021 (clobber (reg:CC CC_REGNUM))]
9022 "TARGET_ARM"
9023 "*
9024 output_asm_insn (\"cmp\\t%2, %3\", operands);
9025 if (which_alternative != 0)
9026 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9027 return \"sub%d4\\t%0, %1, #1\";
9028 "
9029 [(set_attr "conds" "clob")
9030 (set_attr "length" "8,12")
9031 (set_attr "type" "multiple")]
9032 )
9033
9034 (define_insn "*cmp_ite0"
9035 [(set (match_operand 6 "dominant_cc_register" "")
9036 (compare
9037 (if_then_else:SI
9038 (match_operator 4 "arm_comparison_operator"
9039 [(match_operand:SI 0 "s_register_operand"
9040 "l,l,l,r,r,r,r,r,r")
9041 (match_operand:SI 1 "arm_add_operand"
9042 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9043 (match_operator:SI 5 "arm_comparison_operator"
9044 [(match_operand:SI 2 "s_register_operand"
9045 "l,r,r,l,l,r,r,r,r")
9046 (match_operand:SI 3 "arm_add_operand"
9047 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9048 (const_int 0))
9049 (const_int 0)))]
9050 "TARGET_32BIT"
9051 "*
9052 {
9053 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9054 {
9055 {\"cmp%d5\\t%0, %1\",
9056 \"cmp%d4\\t%2, %3\"},
9057 {\"cmn%d5\\t%0, #%n1\",
9058 \"cmp%d4\\t%2, %3\"},
9059 {\"cmp%d5\\t%0, %1\",
9060 \"cmn%d4\\t%2, #%n3\"},
9061 {\"cmn%d5\\t%0, #%n1\",
9062 \"cmn%d4\\t%2, #%n3\"}
9063 };
9064 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9065 {
9066 {\"cmp\\t%2, %3\",
9067 \"cmp\\t%0, %1\"},
9068 {\"cmp\\t%2, %3\",
9069 \"cmn\\t%0, #%n1\"},
9070 {\"cmn\\t%2, #%n3\",
9071 \"cmp\\t%0, %1\"},
9072 {\"cmn\\t%2, #%n3\",
9073 \"cmn\\t%0, #%n1\"}
9074 };
9075 static const char * const ite[2] =
9076 {
9077 \"it\\t%d5\",
9078 \"it\\t%d4\"
9079 };
9080 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9081 CMP_CMP, CMN_CMP, CMP_CMP,
9082 CMN_CMP, CMP_CMN, CMN_CMN};
9083 int swap =
9084 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9085
9086 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9087 if (TARGET_THUMB2) {
9088 output_asm_insn (ite[swap], operands);
9089 }
9090 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9091 return \"\";
9092 }"
9093 [(set_attr "conds" "set")
9094 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9095 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9096 (set_attr "type" "multiple")
9097 (set_attr_alternative "length"
9098 [(const_int 6)
9099 (const_int 8)
9100 (const_int 8)
9101 (const_int 8)
9102 (const_int 8)
9103 (if_then_else (eq_attr "is_thumb" "no")
9104 (const_int 8)
9105 (const_int 10))
9106 (if_then_else (eq_attr "is_thumb" "no")
9107 (const_int 8)
9108 (const_int 10))
9109 (if_then_else (eq_attr "is_thumb" "no")
9110 (const_int 8)
9111 (const_int 10))
9112 (if_then_else (eq_attr "is_thumb" "no")
9113 (const_int 8)
9114 (const_int 10))])]
9115 )
9116
9117 (define_insn "*cmp_ite1"
9118 [(set (match_operand 6 "dominant_cc_register" "")
9119 (compare
9120 (if_then_else:SI
9121 (match_operator 4 "arm_comparison_operator"
9122 [(match_operand:SI 0 "s_register_operand"
9123 "l,l,l,r,r,r,r,r,r")
9124 (match_operand:SI 1 "arm_add_operand"
9125 "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9126 (match_operator:SI 5 "arm_comparison_operator"
9127 [(match_operand:SI 2 "s_register_operand"
9128 "l,r,r,l,l,r,r,r,r")
9129 (match_operand:SI 3 "arm_add_operand"
9130 "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9131 (const_int 1))
9132 (const_int 0)))]
9133 "TARGET_32BIT"
9134 "*
9135 {
9136 static const char * const cmp1[NUM_OF_COND_CMP][2] =
9137 {
9138 {\"cmp\\t%0, %1\",
9139 \"cmp\\t%2, %3\"},
9140 {\"cmn\\t%0, #%n1\",
9141 \"cmp\\t%2, %3\"},
9142 {\"cmp\\t%0, %1\",
9143 \"cmn\\t%2, #%n3\"},
9144 {\"cmn\\t%0, #%n1\",
9145 \"cmn\\t%2, #%n3\"}
9146 };
9147 static const char * const cmp2[NUM_OF_COND_CMP][2] =
9148 {
9149 {\"cmp%d4\\t%2, %3\",
9150 \"cmp%D5\\t%0, %1\"},
9151 {\"cmp%d4\\t%2, %3\",
9152 \"cmn%D5\\t%0, #%n1\"},
9153 {\"cmn%d4\\t%2, #%n3\",
9154 \"cmp%D5\\t%0, %1\"},
9155 {\"cmn%d4\\t%2, #%n3\",
9156 \"cmn%D5\\t%0, #%n1\"}
9157 };
9158 static const char * const ite[2] =
9159 {
9160 \"it\\t%d4\",
9161 \"it\\t%D5\"
9162 };
9163 static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9164 CMP_CMP, CMN_CMP, CMP_CMP,
9165 CMN_CMP, CMP_CMN, CMN_CMN};
9166 int swap =
9167 comparison_dominates_p (GET_CODE (operands[5]),
9168 reverse_condition (GET_CODE (operands[4])));
9169
9170 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9171 if (TARGET_THUMB2) {
9172 output_asm_insn (ite[swap], operands);
9173 }
9174 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9175 return \"\";
9176 }"
9177 [(set_attr "conds" "set")
9178 (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9179 (set_attr "enabled_for_short_it" "yes,no,no,no,no,no,no,no,no")
9180 (set_attr_alternative "length"
9181 [(const_int 6)
9182 (const_int 8)
9183 (const_int 8)
9184 (const_int 8)
9185 (const_int 8)
9186 (if_then_else (eq_attr "is_thumb" "no")
9187 (const_int 8)
9188 (const_int 10))
9189 (if_then_else (eq_attr "is_thumb" "no")
9190 (const_int 8)
9191 (const_int 10))
9192 (if_then_else (eq_attr "is_thumb" "no")
9193 (const_int 8)
9194 (const_int 10))
9195 (if_then_else (eq_attr "is_thumb" "no")
9196 (const_int 8)
9197 (const_int 10))])
9198 (set_attr "type" "multiple")]
9199 )
9200
9201 (define_insn "*cmp_and"
9202 [(set (match_operand 6 "dominant_cc_register" "")
9203 (compare
9204 (and:SI
9205 (match_operator 4 "arm_comparison_operator"
9206 [(match_operand:SI 0 "s_register_operand"
9207 "l,l,l,r,r,r,r,r,r,r")
9208 (match_operand:SI 1 "arm_add_operand"
9209 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
9210 (match_operator:SI 5 "arm_comparison_operator"
9211 [(match_operand:SI 2 "s_register_operand"
9212 "l,r,r,l,l,r,r,r,r,r")
9213 (match_operand:SI 3 "arm_add_operand"
9214 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
9215 (const_int 0)))]
9216 "TARGET_32BIT"
9217 "*
9218 {
9219 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9220 {
9221 {\"cmp%d5\\t%0, %1\",
9222 \"cmp%d4\\t%2, %3\"},
9223 {\"cmn%d5\\t%0, #%n1\",
9224 \"cmp%d4\\t%2, %3\"},
9225 {\"cmp%d5\\t%0, %1\",
9226 \"cmn%d4\\t%2, #%n3\"},
9227 {\"cmn%d5\\t%0, #%n1\",
9228 \"cmn%d4\\t%2, #%n3\"}
9229 };
9230 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9231 {
9232 {\"cmp\\t%2, %3\",
9233 \"cmp\\t%0, %1\"},
9234 {\"cmp\\t%2, %3\",
9235 \"cmn\\t%0, #%n1\"},
9236 {\"cmn\\t%2, #%n3\",
9237 \"cmp\\t%0, %1\"},
9238 {\"cmn\\t%2, #%n3\",
9239 \"cmn\\t%0, #%n1\"}
9240 };
9241 static const char *const ite[2] =
9242 {
9243 \"it\\t%d5\",
9244 \"it\\t%d4\"
9245 };
9246 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9247 CMP_CMP, CMN_CMP, CMP_CMP,
9248 CMP_CMP, CMN_CMP, CMP_CMN,
9249 CMN_CMN};
9250 int swap =
9251 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9252
9253 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9254 if (TARGET_THUMB2) {
9255 output_asm_insn (ite[swap], operands);
9256 }
9257 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9258 return \"\";
9259 }"
9260 [(set_attr "conds" "set")
9261 (set_attr "predicable" "no")
9262 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9263 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
9264 (set_attr_alternative "length"
9265 [(const_int 6)
9266 (const_int 8)
9267 (const_int 8)
9268 (const_int 8)
9269 (const_int 8)
9270 (const_int 6)
9271 (if_then_else (eq_attr "is_thumb" "no")
9272 (const_int 8)
9273 (const_int 10))
9274 (if_then_else (eq_attr "is_thumb" "no")
9275 (const_int 8)
9276 (const_int 10))
9277 (if_then_else (eq_attr "is_thumb" "no")
9278 (const_int 8)
9279 (const_int 10))
9280 (if_then_else (eq_attr "is_thumb" "no")
9281 (const_int 8)
9282 (const_int 10))])
9283 (set_attr "type" "multiple")]
9284 )
9285
9286 (define_insn "*cmp_ior"
9287 [(set (match_operand 6 "dominant_cc_register" "")
9288 (compare
9289 (ior:SI
9290 (match_operator 4 "arm_comparison_operator"
9291 [(match_operand:SI 0 "s_register_operand"
9292 "l,l,l,r,r,r,r,r,r,r")
9293 (match_operand:SI 1 "arm_add_operand"
9294 "lPy,lPy,lPy,rI,L,r,rI,L,rI,L")])
9295 (match_operator:SI 5 "arm_comparison_operator"
9296 [(match_operand:SI 2 "s_register_operand"
9297 "l,r,r,l,l,r,r,r,r,r")
9298 (match_operand:SI 3 "arm_add_operand"
9299 "lPy,rI,L,lPy,lPy,r,rI,rI,L,L")]))
9300 (const_int 0)))]
9301 "TARGET_32BIT"
9302 "*
9303 {
9304 static const char *const cmp1[NUM_OF_COND_CMP][2] =
9305 {
9306 {\"cmp\\t%0, %1\",
9307 \"cmp\\t%2, %3\"},
9308 {\"cmn\\t%0, #%n1\",
9309 \"cmp\\t%2, %3\"},
9310 {\"cmp\\t%0, %1\",
9311 \"cmn\\t%2, #%n3\"},
9312 {\"cmn\\t%0, #%n1\",
9313 \"cmn\\t%2, #%n3\"}
9314 };
9315 static const char *const cmp2[NUM_OF_COND_CMP][2] =
9316 {
9317 {\"cmp%D4\\t%2, %3\",
9318 \"cmp%D5\\t%0, %1\"},
9319 {\"cmp%D4\\t%2, %3\",
9320 \"cmn%D5\\t%0, #%n1\"},
9321 {\"cmn%D4\\t%2, #%n3\",
9322 \"cmp%D5\\t%0, %1\"},
9323 {\"cmn%D4\\t%2, #%n3\",
9324 \"cmn%D5\\t%0, #%n1\"}
9325 };
9326 static const char *const ite[2] =
9327 {
9328 \"it\\t%D4\",
9329 \"it\\t%D5\"
9330 };
9331 static const int cmp_idx[] = {CMP_CMP, CMP_CMP, CMP_CMN,
9332 CMP_CMP, CMN_CMP, CMP_CMP,
9333 CMP_CMP, CMN_CMP, CMP_CMN,
9334 CMN_CMN};
9335 int swap =
9336 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9337
9338 output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9339 if (TARGET_THUMB2) {
9340 output_asm_insn (ite[swap], operands);
9341 }
9342 output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9343 return \"\";
9344 }
9345 "
9346 [(set_attr "conds" "set")
9347 (set_attr "arch" "t2,t2,t2,t2,t2,t2,any,any,any,any")
9348 (set_attr "enabled_for_short_it" "yes,no,no,no,no,yes,no,no,no,no")
9349 (set_attr_alternative "length"
9350 [(const_int 6)
9351 (const_int 8)
9352 (const_int 8)
9353 (const_int 8)
9354 (const_int 8)
9355 (const_int 6)
9356 (if_then_else (eq_attr "is_thumb" "no")
9357 (const_int 8)
9358 (const_int 10))
9359 (if_then_else (eq_attr "is_thumb" "no")
9360 (const_int 8)
9361 (const_int 10))
9362 (if_then_else (eq_attr "is_thumb" "no")
9363 (const_int 8)
9364 (const_int 10))
9365 (if_then_else (eq_attr "is_thumb" "no")
9366 (const_int 8)
9367 (const_int 10))])
9368 (set_attr "type" "multiple")]
9369 )
9370
9371 (define_insn_and_split "*ior_scc_scc"
9372 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9373 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9374 [(match_operand:SI 1 "s_register_operand" "l,r")
9375 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9376 (match_operator:SI 6 "arm_comparison_operator"
9377 [(match_operand:SI 4 "s_register_operand" "l,r")
9378 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9379 (clobber (reg:CC CC_REGNUM))]
9380 "TARGET_32BIT
9381 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9382 != CCmode)"
9383 "#"
9384 "TARGET_32BIT && reload_completed"
9385 [(set (match_dup 7)
9386 (compare
9387 (ior:SI
9388 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9389 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9390 (const_int 0)))
9391 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9392 "operands[7]
9393 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9394 DOM_CC_X_OR_Y),
9395 CC_REGNUM);"
9396 [(set_attr "conds" "clob")
9397 (set_attr "enabled_for_short_it" "yes,no")
9398 (set_attr "length" "16")
9399 (set_attr "type" "multiple")]
9400 )
9401
9402 ; If the above pattern is followed by a CMP insn, then the compare is
9403 ; redundant, since we can rework the conditional instruction that follows.
9404 (define_insn_and_split "*ior_scc_scc_cmp"
9405 [(set (match_operand 0 "dominant_cc_register" "")
9406 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9407 [(match_operand:SI 1 "s_register_operand" "l,r")
9408 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9409 (match_operator:SI 6 "arm_comparison_operator"
9410 [(match_operand:SI 4 "s_register_operand" "l,r")
9411 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9412 (const_int 0)))
9413 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9414 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9415 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9416 "TARGET_32BIT"
9417 "#"
9418 "TARGET_32BIT && reload_completed"
9419 [(set (match_dup 0)
9420 (compare
9421 (ior:SI
9422 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9423 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9424 (const_int 0)))
9425 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9426 ""
9427 [(set_attr "conds" "set")
9428 (set_attr "enabled_for_short_it" "yes,no")
9429 (set_attr "length" "16")
9430 (set_attr "type" "multiple")]
9431 )
9432
9433 (define_insn_and_split "*and_scc_scc"
9434 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
9435 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9436 [(match_operand:SI 1 "s_register_operand" "l,r")
9437 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9438 (match_operator:SI 6 "arm_comparison_operator"
9439 [(match_operand:SI 4 "s_register_operand" "l,r")
9440 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")])))
9441 (clobber (reg:CC CC_REGNUM))]
9442 "TARGET_32BIT
9443 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9444 != CCmode)"
9445 "#"
9446 "TARGET_32BIT && reload_completed
9447 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9448 != CCmode)"
9449 [(set (match_dup 7)
9450 (compare
9451 (and:SI
9452 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9453 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9454 (const_int 0)))
9455 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9456 "operands[7]
9457 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9458 DOM_CC_X_AND_Y),
9459 CC_REGNUM);"
9460 [(set_attr "conds" "clob")
9461 (set_attr "enabled_for_short_it" "yes,no")
9462 (set_attr "length" "16")
9463 (set_attr "type" "multiple")]
9464 )
9465
9466 ; If the above pattern is followed by a CMP insn, then the compare is
9467 ; redundant, since we can rework the conditional instruction that follows.
9468 (define_insn_and_split "*and_scc_scc_cmp"
9469 [(set (match_operand 0 "dominant_cc_register" "")
9470 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9471 [(match_operand:SI 1 "s_register_operand" "l,r")
9472 (match_operand:SI 2 "arm_add_operand" "lPy,rIL")])
9473 (match_operator:SI 6 "arm_comparison_operator"
9474 [(match_operand:SI 4 "s_register_operand" "l,r")
9475 (match_operand:SI 5 "arm_add_operand" "lPy,rIL")]))
9476 (const_int 0)))
9477 (set (match_operand:SI 7 "s_register_operand" "=Ts,Ts")
9478 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9479 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9480 "TARGET_32BIT"
9481 "#"
9482 "TARGET_32BIT && reload_completed"
9483 [(set (match_dup 0)
9484 (compare
9485 (and:SI
9486 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9487 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9488 (const_int 0)))
9489 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9490 ""
9491 [(set_attr "conds" "set")
9492 (set_attr "enabled_for_short_it" "yes,no")
9493 (set_attr "length" "16")
9494 (set_attr "type" "multiple")]
9495 )
9496
9497 ;; If there is no dominance in the comparison, then we can still save an
9498 ;; instruction in the AND case, since we can know that the second compare
9499 ;; need only zero the value if false (if true, then the value is already
9500 ;; correct).
9501 (define_insn_and_split "*and_scc_scc_nodom"
9502 [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
9503 (and:SI (match_operator:SI 3 "arm_comparison_operator"
9504 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9505 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9506 (match_operator:SI 6 "arm_comparison_operator"
9507 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9508 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9509 (clobber (reg:CC CC_REGNUM))]
9510 "TARGET_32BIT
9511 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9512 == CCmode)"
9513 "#"
9514 "TARGET_32BIT && reload_completed"
9515 [(parallel [(set (match_dup 0)
9516 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9517 (clobber (reg:CC CC_REGNUM))])
9518 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9519 (set (match_dup 0)
9520 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9521 (match_dup 0)
9522 (const_int 0)))]
9523 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9524 operands[4], operands[5]),
9525 CC_REGNUM);
9526 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9527 operands[5]);"
9528 [(set_attr "conds" "clob")
9529 (set_attr "length" "20")
9530 (set_attr "type" "multiple")]
9531 )
9532
9533 (define_split
9534 [(set (reg:CC_NOOV CC_REGNUM)
9535 (compare:CC_NOOV (ior:SI
9536 (and:SI (match_operand:SI 0 "s_register_operand" "")
9537 (const_int 1))
9538 (match_operator:SI 1 "arm_comparison_operator"
9539 [(match_operand:SI 2 "s_register_operand" "")
9540 (match_operand:SI 3 "arm_add_operand" "")]))
9541 (const_int 0)))
9542 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9543 "TARGET_ARM"
9544 [(set (match_dup 4)
9545 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9546 (match_dup 0)))
9547 (set (reg:CC_NOOV CC_REGNUM)
9548 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9549 (const_int 0)))]
9550 "")
9551
9552 (define_split
9553 [(set (reg:CC_NOOV CC_REGNUM)
9554 (compare:CC_NOOV (ior:SI
9555 (match_operator:SI 1 "arm_comparison_operator"
9556 [(match_operand:SI 2 "s_register_operand" "")
9557 (match_operand:SI 3 "arm_add_operand" "")])
9558 (and:SI (match_operand:SI 0 "s_register_operand" "")
9559 (const_int 1)))
9560 (const_int 0)))
9561 (clobber (match_operand:SI 4 "s_register_operand" ""))]
9562 "TARGET_ARM"
9563 [(set (match_dup 4)
9564 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9565 (match_dup 0)))
9566 (set (reg:CC_NOOV CC_REGNUM)
9567 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9568 (const_int 0)))]
9569 "")
9570 ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9571
9572 (define_insn_and_split "*negscc"
9573 [(set (match_operand:SI 0 "s_register_operand" "=r")
9574 (neg:SI (match_operator 3 "arm_comparison_operator"
9575 [(match_operand:SI 1 "s_register_operand" "r")
9576 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9577 (clobber (reg:CC CC_REGNUM))]
9578 "TARGET_ARM"
9579 "#"
9580 "&& reload_completed"
9581 [(const_int 0)]
9582 {
9583 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
9584
9585 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9586 {
9587 /* Emit mov\\t%0, %1, asr #31 */
9588 emit_insn (gen_rtx_SET (operands[0],
9589 gen_rtx_ASHIFTRT (SImode,
9590 operands[1],
9591 GEN_INT (31))));
9592 DONE;
9593 }
9594 else if (GET_CODE (operands[3]) == NE)
9595 {
9596 /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9597 if (CONST_INT_P (operands[2]))
9598 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9599 gen_int_mode (-INTVAL (operands[2]),
9600 SImode)));
9601 else
9602 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9603
9604 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9605 gen_rtx_NE (SImode,
9606 cc_reg,
9607 const0_rtx),
9608 gen_rtx_SET (operands[0],
9609 GEN_INT (~0))));
9610 DONE;
9611 }
9612 else
9613 {
9614 /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
9615 emit_insn (gen_rtx_SET (cc_reg,
9616 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9617 enum rtx_code rc = GET_CODE (operands[3]);
9618
9619 rc = reverse_condition (rc);
9620 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9621 gen_rtx_fmt_ee (rc,
9622 VOIDmode,
9623 cc_reg,
9624 const0_rtx),
9625 gen_rtx_SET (operands[0], const0_rtx)));
9626 rc = GET_CODE (operands[3]);
9627 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9628 gen_rtx_fmt_ee (rc,
9629 VOIDmode,
9630 cc_reg,
9631 const0_rtx),
9632 gen_rtx_SET (operands[0],
9633 GEN_INT (~0))));
9634 DONE;
9635 }
9636 FAIL;
9637 }
9638 [(set_attr "conds" "clob")
9639 (set_attr "length" "12")
9640 (set_attr "type" "multiple")]
9641 )
9642
9643 (define_insn_and_split "movcond_addsi"
9644 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9645 (if_then_else:SI
9646 (match_operator 5 "comparison_operator"
9647 [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9648 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9649 (const_int 0)])
9650 (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9651 (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9652 (clobber (reg:CC CC_REGNUM))]
9653 "TARGET_32BIT"
9654 "#"
9655 "&& reload_completed"
9656 [(set (reg:CC_NOOV CC_REGNUM)
9657 (compare:CC_NOOV
9658 (plus:SI (match_dup 3)
9659 (match_dup 4))
9660 (const_int 0)))
9661 (set (match_dup 0) (match_dup 1))
9662 (cond_exec (match_dup 6)
9663 (set (match_dup 0) (match_dup 2)))]
9664 "
9665 {
9666 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
9667 operands[3], operands[4]);
9668 enum rtx_code rc = GET_CODE (operands[5]);
9669 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9670 gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
9671 if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
9672 rc = reverse_condition (rc);
9673 else
9674 std::swap (operands[1], operands[2]);
9675
9676 operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9677 }
9678 "
9679 [(set_attr "conds" "clob")
9680 (set_attr "enabled_for_short_it" "no,yes,yes")
9681 (set_attr "type" "multiple")]
9682 )
9683
9684 (define_insn "movcond"
9685 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9686 (if_then_else:SI
9687 (match_operator 5 "arm_comparison_operator"
9688 [(match_operand:SI 3 "s_register_operand" "r,r,r")
9689 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9690 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9691 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9692 (clobber (reg:CC CC_REGNUM))]
9693 "TARGET_ARM"
9694 "*
9695 if (GET_CODE (operands[5]) == LT
9696 && (operands[4] == const0_rtx))
9697 {
9698 if (which_alternative != 1 && REG_P (operands[1]))
9699 {
9700 if (operands[2] == const0_rtx)
9701 return \"and\\t%0, %1, %3, asr #31\";
9702 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9703 }
9704 else if (which_alternative != 0 && REG_P (operands[2]))
9705 {
9706 if (operands[1] == const0_rtx)
9707 return \"bic\\t%0, %2, %3, asr #31\";
9708 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9709 }
9710 /* The only case that falls through to here is when both ops 1 & 2
9711 are constants. */
9712 }
9713
9714 if (GET_CODE (operands[5]) == GE
9715 && (operands[4] == const0_rtx))
9716 {
9717 if (which_alternative != 1 && REG_P (operands[1]))
9718 {
9719 if (operands[2] == const0_rtx)
9720 return \"bic\\t%0, %1, %3, asr #31\";
9721 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9722 }
9723 else if (which_alternative != 0 && REG_P (operands[2]))
9724 {
9725 if (operands[1] == const0_rtx)
9726 return \"and\\t%0, %2, %3, asr #31\";
9727 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9728 }
9729 /* The only case that falls through to here is when both ops 1 & 2
9730 are constants. */
9731 }
9732 if (CONST_INT_P (operands[4])
9733 && !const_ok_for_arm (INTVAL (operands[4])))
9734 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9735 else
9736 output_asm_insn (\"cmp\\t%3, %4\", operands);
9737 if (which_alternative != 0)
9738 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9739 if (which_alternative != 1)
9740 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9741 return \"\";
9742 "
9743 [(set_attr "conds" "clob")
9744 (set_attr "length" "8,8,12")
9745 (set_attr "type" "multiple")]
9746 )
9747
9748 ;; ??? The patterns below need checking for Thumb-2 usefulness.
9749
9750 (define_insn "*ifcompare_plus_move"
9751 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9752 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9753 [(match_operand:SI 4 "s_register_operand" "r,r")
9754 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9755 (plus:SI
9756 (match_operand:SI 2 "s_register_operand" "r,r")
9757 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9758 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9759 (clobber (reg:CC CC_REGNUM))]
9760 "TARGET_ARM"
9761 "#"
9762 [(set_attr "conds" "clob")
9763 (set_attr "length" "8,12")
9764 (set_attr "type" "multiple")]
9765 )
9766
9767 (define_insn "*if_plus_move"
9768 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9769 (if_then_else:SI
9770 (match_operator 4 "arm_comparison_operator"
9771 [(match_operand 5 "cc_register" "") (const_int 0)])
9772 (plus:SI
9773 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9774 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9775 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9776 "TARGET_ARM"
9777 "@
9778 add%d4\\t%0, %2, %3
9779 sub%d4\\t%0, %2, #%n3
9780 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9781 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9782 [(set_attr "conds" "use")
9783 (set_attr "length" "4,4,8,8")
9784 (set_attr_alternative "type"
9785 [(if_then_else (match_operand 3 "const_int_operand" "")
9786 (const_string "alu_imm" )
9787 (const_string "alu_sreg"))
9788 (const_string "alu_imm")
9789 (const_string "multiple")
9790 (const_string "multiple")])]
9791 )
9792
9793 (define_insn "*ifcompare_move_plus"
9794 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9795 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9796 [(match_operand:SI 4 "s_register_operand" "r,r")
9797 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9798 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9799 (plus:SI
9800 (match_operand:SI 2 "s_register_operand" "r,r")
9801 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9802 (clobber (reg:CC CC_REGNUM))]
9803 "TARGET_ARM"
9804 "#"
9805 [(set_attr "conds" "clob")
9806 (set_attr "length" "8,12")
9807 (set_attr "type" "multiple")]
9808 )
9809
9810 (define_insn "*if_move_plus"
9811 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9812 (if_then_else:SI
9813 (match_operator 4 "arm_comparison_operator"
9814 [(match_operand 5 "cc_register" "") (const_int 0)])
9815 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9816 (plus:SI
9817 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9818 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9819 "TARGET_ARM"
9820 "@
9821 add%D4\\t%0, %2, %3
9822 sub%D4\\t%0, %2, #%n3
9823 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9824 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9825 [(set_attr "conds" "use")
9826 (set_attr "length" "4,4,8,8")
9827 (set_attr_alternative "type"
9828 [(if_then_else (match_operand 3 "const_int_operand" "")
9829 (const_string "alu_imm" )
9830 (const_string "alu_sreg"))
9831 (const_string "alu_imm")
9832 (const_string "multiple")
9833 (const_string "multiple")])]
9834 )
9835
9836 (define_insn "*ifcompare_arith_arith"
9837 [(set (match_operand:SI 0 "s_register_operand" "=r")
9838 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9839 [(match_operand:SI 5 "s_register_operand" "r")
9840 (match_operand:SI 6 "arm_add_operand" "rIL")])
9841 (match_operator:SI 8 "shiftable_operator"
9842 [(match_operand:SI 1 "s_register_operand" "r")
9843 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9844 (match_operator:SI 7 "shiftable_operator"
9845 [(match_operand:SI 3 "s_register_operand" "r")
9846 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9847 (clobber (reg:CC CC_REGNUM))]
9848 "TARGET_ARM"
9849 "#"
9850 [(set_attr "conds" "clob")
9851 (set_attr "length" "12")
9852 (set_attr "type" "multiple")]
9853 )
9854
9855 (define_insn "*if_arith_arith"
9856 [(set (match_operand:SI 0 "s_register_operand" "=r")
9857 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9858 [(match_operand 8 "cc_register" "") (const_int 0)])
9859 (match_operator:SI 6 "shiftable_operator"
9860 [(match_operand:SI 1 "s_register_operand" "r")
9861 (match_operand:SI 2 "arm_rhs_operand" "rI")])
9862 (match_operator:SI 7 "shiftable_operator"
9863 [(match_operand:SI 3 "s_register_operand" "r")
9864 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9865 "TARGET_ARM"
9866 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9867 [(set_attr "conds" "use")
9868 (set_attr "length" "8")
9869 (set_attr "type" "multiple")]
9870 )
9871
9872 (define_insn "*ifcompare_arith_move"
9873 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9874 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9875 [(match_operand:SI 2 "s_register_operand" "r,r")
9876 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9877 (match_operator:SI 7 "shiftable_operator"
9878 [(match_operand:SI 4 "s_register_operand" "r,r")
9879 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9880 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9881 (clobber (reg:CC CC_REGNUM))]
9882 "TARGET_ARM"
9883 "*
9884 /* If we have an operation where (op x 0) is the identity operation and
9885 the conditional operator is LT or GE and we are comparing against zero and
9886 everything is in registers then we can do this in two instructions. */
9887 if (operands[3] == const0_rtx
9888 && GET_CODE (operands[7]) != AND
9889 && REG_P (operands[5])
9890 && REG_P (operands[1])
9891 && REGNO (operands[1]) == REGNO (operands[4])
9892 && REGNO (operands[4]) != REGNO (operands[0]))
9893 {
9894 if (GET_CODE (operands[6]) == LT)
9895 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9896 else if (GET_CODE (operands[6]) == GE)
9897 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9898 }
9899 if (CONST_INT_P (operands[3])
9900 && !const_ok_for_arm (INTVAL (operands[3])))
9901 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9902 else
9903 output_asm_insn (\"cmp\\t%2, %3\", operands);
9904 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9905 if (which_alternative != 0)
9906 return \"mov%D6\\t%0, %1\";
9907 return \"\";
9908 "
9909 [(set_attr "conds" "clob")
9910 (set_attr "length" "8,12")
9911 (set_attr "type" "multiple")]
9912 )
9913
9914 (define_insn "*if_arith_move"
9915 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9916 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9917 [(match_operand 6 "cc_register" "") (const_int 0)])
9918 (match_operator:SI 5 "shiftable_operator"
9919 [(match_operand:SI 2 "s_register_operand" "r,r")
9920 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9921 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9922 "TARGET_ARM"
9923 "@
9924 %I5%d4\\t%0, %2, %3
9925 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9926 [(set_attr "conds" "use")
9927 (set_attr "length" "4,8")
9928 (set_attr_alternative "type"
9929 [(if_then_else (match_operand 3 "const_int_operand" "")
9930 (const_string "alu_shift_imm" )
9931 (const_string "alu_shift_reg"))
9932 (const_string "multiple")])]
9933 )
9934
9935 (define_insn "*ifcompare_move_arith"
9936 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9937 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9938 [(match_operand:SI 4 "s_register_operand" "r,r")
9939 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9940 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9941 (match_operator:SI 7 "shiftable_operator"
9942 [(match_operand:SI 2 "s_register_operand" "r,r")
9943 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9944 (clobber (reg:CC CC_REGNUM))]
9945 "TARGET_ARM"
9946 "*
9947 /* If we have an operation where (op x 0) is the identity operation and
9948 the conditional operator is LT or GE and we are comparing against zero and
9949 everything is in registers then we can do this in two instructions */
9950 if (operands[5] == const0_rtx
9951 && GET_CODE (operands[7]) != AND
9952 && REG_P (operands[3])
9953 && REG_P (operands[1])
9954 && REGNO (operands[1]) == REGNO (operands[2])
9955 && REGNO (operands[2]) != REGNO (operands[0]))
9956 {
9957 if (GET_CODE (operands[6]) == GE)
9958 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9959 else if (GET_CODE (operands[6]) == LT)
9960 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9961 }
9962
9963 if (CONST_INT_P (operands[5])
9964 && !const_ok_for_arm (INTVAL (operands[5])))
9965 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9966 else
9967 output_asm_insn (\"cmp\\t%4, %5\", operands);
9968
9969 if (which_alternative != 0)
9970 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9971 return \"%I7%D6\\t%0, %2, %3\";
9972 "
9973 [(set_attr "conds" "clob")
9974 (set_attr "length" "8,12")
9975 (set_attr "type" "multiple")]
9976 )
9977
9978 (define_insn "*if_move_arith"
9979 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9980 (if_then_else:SI
9981 (match_operator 4 "arm_comparison_operator"
9982 [(match_operand 6 "cc_register" "") (const_int 0)])
9983 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9984 (match_operator:SI 5 "shiftable_operator"
9985 [(match_operand:SI 2 "s_register_operand" "r,r")
9986 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9987 "TARGET_ARM"
9988 "@
9989 %I5%D4\\t%0, %2, %3
9990 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9991 [(set_attr "conds" "use")
9992 (set_attr "length" "4,8")
9993 (set_attr_alternative "type"
9994 [(if_then_else (match_operand 3 "const_int_operand" "")
9995 (const_string "alu_shift_imm" )
9996 (const_string "alu_shift_reg"))
9997 (const_string "multiple")])]
9998 )
9999
10000 (define_insn "*ifcompare_move_not"
10001 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10002 (if_then_else:SI
10003 (match_operator 5 "arm_comparison_operator"
10004 [(match_operand:SI 3 "s_register_operand" "r,r")
10005 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10006 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10007 (not:SI
10008 (match_operand:SI 2 "s_register_operand" "r,r"))))
10009 (clobber (reg:CC CC_REGNUM))]
10010 "TARGET_ARM"
10011 "#"
10012 [(set_attr "conds" "clob")
10013 (set_attr "length" "8,12")
10014 (set_attr "type" "multiple")]
10015 )
10016
10017 (define_insn "*if_move_not"
10018 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10019 (if_then_else:SI
10020 (match_operator 4 "arm_comparison_operator"
10021 [(match_operand 3 "cc_register" "") (const_int 0)])
10022 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10023 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10024 "TARGET_ARM"
10025 "@
10026 mvn%D4\\t%0, %2
10027 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10028 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10029 [(set_attr "conds" "use")
10030 (set_attr "type" "mvn_reg")
10031 (set_attr "length" "4,8,8")
10032 (set_attr "type" "mvn_reg,multiple,multiple")]
10033 )
10034
10035 (define_insn "*ifcompare_not_move"
10036 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10037 (if_then_else:SI
10038 (match_operator 5 "arm_comparison_operator"
10039 [(match_operand:SI 3 "s_register_operand" "r,r")
10040 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10041 (not:SI
10042 (match_operand:SI 2 "s_register_operand" "r,r"))
10043 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10044 (clobber (reg:CC CC_REGNUM))]
10045 "TARGET_ARM"
10046 "#"
10047 [(set_attr "conds" "clob")
10048 (set_attr "length" "8,12")
10049 (set_attr "type" "multiple")]
10050 )
10051
10052 (define_insn "*if_not_move"
10053 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10054 (if_then_else:SI
10055 (match_operator 4 "arm_comparison_operator"
10056 [(match_operand 3 "cc_register" "") (const_int 0)])
10057 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10058 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10059 "TARGET_ARM"
10060 "@
10061 mvn%d4\\t%0, %2
10062 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10063 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10064 [(set_attr "conds" "use")
10065 (set_attr "type" "mvn_reg,multiple,multiple")
10066 (set_attr "length" "4,8,8")]
10067 )
10068
10069 (define_insn "*ifcompare_shift_move"
10070 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10071 (if_then_else:SI
10072 (match_operator 6 "arm_comparison_operator"
10073 [(match_operand:SI 4 "s_register_operand" "r,r")
10074 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10075 (match_operator:SI 7 "shift_operator"
10076 [(match_operand:SI 2 "s_register_operand" "r,r")
10077 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10078 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10079 (clobber (reg:CC CC_REGNUM))]
10080 "TARGET_ARM"
10081 "#"
10082 [(set_attr "conds" "clob")
10083 (set_attr "length" "8,12")
10084 (set_attr "type" "multiple")]
10085 )
10086
10087 (define_insn "*if_shift_move"
10088 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10089 (if_then_else:SI
10090 (match_operator 5 "arm_comparison_operator"
10091 [(match_operand 6 "cc_register" "") (const_int 0)])
10092 (match_operator:SI 4 "shift_operator"
10093 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10094 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10095 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10096 "TARGET_ARM"
10097 "@
10098 mov%d5\\t%0, %2%S4
10099 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10100 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10101 [(set_attr "conds" "use")
10102 (set_attr "shift" "2")
10103 (set_attr "length" "4,8,8")
10104 (set_attr_alternative "type"
10105 [(if_then_else (match_operand 3 "const_int_operand" "")
10106 (const_string "mov_shift" )
10107 (const_string "mov_shift_reg"))
10108 (const_string "multiple")
10109 (const_string "multiple")])]
10110 )
10111
10112 (define_insn "*ifcompare_move_shift"
10113 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10114 (if_then_else:SI
10115 (match_operator 6 "arm_comparison_operator"
10116 [(match_operand:SI 4 "s_register_operand" "r,r")
10117 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10118 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10119 (match_operator:SI 7 "shift_operator"
10120 [(match_operand:SI 2 "s_register_operand" "r,r")
10121 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10122 (clobber (reg:CC CC_REGNUM))]
10123 "TARGET_ARM"
10124 "#"
10125 [(set_attr "conds" "clob")
10126 (set_attr "length" "8,12")
10127 (set_attr "type" "multiple")]
10128 )
10129
10130 (define_insn "*if_move_shift"
10131 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10132 (if_then_else:SI
10133 (match_operator 5 "arm_comparison_operator"
10134 [(match_operand 6 "cc_register" "") (const_int 0)])
10135 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10136 (match_operator:SI 4 "shift_operator"
10137 [(match_operand:SI 2 "s_register_operand" "r,r,r")
10138 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10139 "TARGET_ARM"
10140 "@
10141 mov%D5\\t%0, %2%S4
10142 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10143 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10144 [(set_attr "conds" "use")
10145 (set_attr "shift" "2")
10146 (set_attr "length" "4,8,8")
10147 (set_attr_alternative "type"
10148 [(if_then_else (match_operand 3 "const_int_operand" "")
10149 (const_string "mov_shift" )
10150 (const_string "mov_shift_reg"))
10151 (const_string "multiple")
10152 (const_string "multiple")])]
10153 )
10154
10155 (define_insn "*ifcompare_shift_shift"
10156 [(set (match_operand:SI 0 "s_register_operand" "=r")
10157 (if_then_else:SI
10158 (match_operator 7 "arm_comparison_operator"
10159 [(match_operand:SI 5 "s_register_operand" "r")
10160 (match_operand:SI 6 "arm_add_operand" "rIL")])
10161 (match_operator:SI 8 "shift_operator"
10162 [(match_operand:SI 1 "s_register_operand" "r")
10163 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10164 (match_operator:SI 9 "shift_operator"
10165 [(match_operand:SI 3 "s_register_operand" "r")
10166 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10167 (clobber (reg:CC CC_REGNUM))]
10168 "TARGET_ARM"
10169 "#"
10170 [(set_attr "conds" "clob")
10171 (set_attr "length" "12")
10172 (set_attr "type" "multiple")]
10173 )
10174
10175 (define_insn "*if_shift_shift"
10176 [(set (match_operand:SI 0 "s_register_operand" "=r")
10177 (if_then_else:SI
10178 (match_operator 5 "arm_comparison_operator"
10179 [(match_operand 8 "cc_register" "") (const_int 0)])
10180 (match_operator:SI 6 "shift_operator"
10181 [(match_operand:SI 1 "s_register_operand" "r")
10182 (match_operand:SI 2 "arm_rhs_operand" "rM")])
10183 (match_operator:SI 7 "shift_operator"
10184 [(match_operand:SI 3 "s_register_operand" "r")
10185 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10186 "TARGET_ARM"
10187 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10188 [(set_attr "conds" "use")
10189 (set_attr "shift" "1")
10190 (set_attr "length" "8")
10191 (set (attr "type") (if_then_else
10192 (and (match_operand 2 "const_int_operand" "")
10193 (match_operand 4 "const_int_operand" ""))
10194 (const_string "mov_shift")
10195 (const_string "mov_shift_reg")))]
10196 )
10197
10198 (define_insn "*ifcompare_not_arith"
10199 [(set (match_operand:SI 0 "s_register_operand" "=r")
10200 (if_then_else:SI
10201 (match_operator 6 "arm_comparison_operator"
10202 [(match_operand:SI 4 "s_register_operand" "r")
10203 (match_operand:SI 5 "arm_add_operand" "rIL")])
10204 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10205 (match_operator:SI 7 "shiftable_operator"
10206 [(match_operand:SI 2 "s_register_operand" "r")
10207 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10208 (clobber (reg:CC CC_REGNUM))]
10209 "TARGET_ARM"
10210 "#"
10211 [(set_attr "conds" "clob")
10212 (set_attr "length" "12")
10213 (set_attr "type" "multiple")]
10214 )
10215
10216 (define_insn "*if_not_arith"
10217 [(set (match_operand:SI 0 "s_register_operand" "=r")
10218 (if_then_else:SI
10219 (match_operator 5 "arm_comparison_operator"
10220 [(match_operand 4 "cc_register" "") (const_int 0)])
10221 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10222 (match_operator:SI 6 "shiftable_operator"
10223 [(match_operand:SI 2 "s_register_operand" "r")
10224 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10225 "TARGET_ARM"
10226 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10227 [(set_attr "conds" "use")
10228 (set_attr "type" "mvn_reg")
10229 (set_attr "length" "8")]
10230 )
10231
10232 (define_insn "*ifcompare_arith_not"
10233 [(set (match_operand:SI 0 "s_register_operand" "=r")
10234 (if_then_else:SI
10235 (match_operator 6 "arm_comparison_operator"
10236 [(match_operand:SI 4 "s_register_operand" "r")
10237 (match_operand:SI 5 "arm_add_operand" "rIL")])
10238 (match_operator:SI 7 "shiftable_operator"
10239 [(match_operand:SI 2 "s_register_operand" "r")
10240 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10241 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10242 (clobber (reg:CC CC_REGNUM))]
10243 "TARGET_ARM"
10244 "#"
10245 [(set_attr "conds" "clob")
10246 (set_attr "length" "12")
10247 (set_attr "type" "multiple")]
10248 )
10249
10250 (define_insn "*if_arith_not"
10251 [(set (match_operand:SI 0 "s_register_operand" "=r")
10252 (if_then_else:SI
10253 (match_operator 5 "arm_comparison_operator"
10254 [(match_operand 4 "cc_register" "") (const_int 0)])
10255 (match_operator:SI 6 "shiftable_operator"
10256 [(match_operand:SI 2 "s_register_operand" "r")
10257 (match_operand:SI 3 "arm_rhs_operand" "rI")])
10258 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10259 "TARGET_ARM"
10260 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10261 [(set_attr "conds" "use")
10262 (set_attr "type" "multiple")
10263 (set_attr "length" "8")]
10264 )
10265
10266 (define_insn "*ifcompare_neg_move"
10267 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10268 (if_then_else:SI
10269 (match_operator 5 "arm_comparison_operator"
10270 [(match_operand:SI 3 "s_register_operand" "r,r")
10271 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10272 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10273 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10274 (clobber (reg:CC CC_REGNUM))]
10275 "TARGET_ARM"
10276 "#"
10277 [(set_attr "conds" "clob")
10278 (set_attr "length" "8,12")
10279 (set_attr "type" "multiple")]
10280 )
10281
10282 (define_insn_and_split "*if_neg_move"
10283 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10284 (if_then_else:SI
10285 (match_operator 4 "arm_comparison_operator"
10286 [(match_operand 3 "cc_register" "") (const_int 0)])
10287 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
10288 (match_operand:SI 1 "s_register_operand" "0,0")))]
10289 "TARGET_32BIT"
10290 "#"
10291 "&& reload_completed"
10292 [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
10293 (set (match_dup 0) (neg:SI (match_dup 2))))]
10294 ""
10295 [(set_attr "conds" "use")
10296 (set_attr "length" "4")
10297 (set_attr "arch" "t2,32")
10298 (set_attr "enabled_for_short_it" "yes,no")
10299 (set_attr "type" "logic_shift_imm")]
10300 )
10301
10302 (define_insn "*ifcompare_move_neg"
10303 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10304 (if_then_else:SI
10305 (match_operator 5 "arm_comparison_operator"
10306 [(match_operand:SI 3 "s_register_operand" "r,r")
10307 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10308 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10309 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10310 (clobber (reg:CC CC_REGNUM))]
10311 "TARGET_ARM"
10312 "#"
10313 [(set_attr "conds" "clob")
10314 (set_attr "length" "8,12")
10315 (set_attr "type" "multiple")]
10316 )
10317
10318 (define_insn_and_split "*if_move_neg"
10319 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
10320 (if_then_else:SI
10321 (match_operator 4 "arm_comparison_operator"
10322 [(match_operand 3 "cc_register" "") (const_int 0)])
10323 (match_operand:SI 1 "s_register_operand" "0,0")
10324 (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
10325 "TARGET_32BIT"
10326 "#"
10327 "&& reload_completed"
10328 [(cond_exec (match_dup 5)
10329 (set (match_dup 0) (neg:SI (match_dup 2))))]
10330 {
10331 machine_mode mode = GET_MODE (operands[3]);
10332 rtx_code rc = GET_CODE (operands[4]);
10333
10334 if (mode == CCFPmode || mode == CCFPEmode)
10335 rc = reverse_condition_maybe_unordered (rc);
10336 else
10337 rc = reverse_condition (rc);
10338
10339 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
10340 }
10341 [(set_attr "conds" "use")
10342 (set_attr "length" "4")
10343 (set_attr "arch" "t2,32")
10344 (set_attr "enabled_for_short_it" "yes,no")
10345 (set_attr "type" "logic_shift_imm")]
10346 )
10347
10348 (define_insn "*arith_adjacentmem"
10349 [(set (match_operand:SI 0 "s_register_operand" "=r")
10350 (match_operator:SI 1 "shiftable_operator"
10351 [(match_operand:SI 2 "memory_operand" "m")
10352 (match_operand:SI 3 "memory_operand" "m")]))
10353 (clobber (match_scratch:SI 4 "=r"))]
10354 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10355 "*
10356 {
10357 rtx ldm[3];
10358 rtx arith[4];
10359 rtx base_reg;
10360 HOST_WIDE_INT val1 = 0, val2 = 0;
10361
10362 if (REGNO (operands[0]) > REGNO (operands[4]))
10363 {
10364 ldm[1] = operands[4];
10365 ldm[2] = operands[0];
10366 }
10367 else
10368 {
10369 ldm[1] = operands[0];
10370 ldm[2] = operands[4];
10371 }
10372
10373 base_reg = XEXP (operands[2], 0);
10374
10375 if (!REG_P (base_reg))
10376 {
10377 val1 = INTVAL (XEXP (base_reg, 1));
10378 base_reg = XEXP (base_reg, 0);
10379 }
10380
10381 if (!REG_P (XEXP (operands[3], 0)))
10382 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10383
10384 arith[0] = operands[0];
10385 arith[3] = operands[1];
10386
10387 if (val1 < val2)
10388 {
10389 arith[1] = ldm[1];
10390 arith[2] = ldm[2];
10391 }
10392 else
10393 {
10394 arith[1] = ldm[2];
10395 arith[2] = ldm[1];
10396 }
10397
10398 ldm[0] = base_reg;
10399 if (val1 !=0 && val2 != 0)
10400 {
10401 rtx ops[3];
10402
10403 if (val1 == 4 || val2 == 4)
10404 /* Other val must be 8, since we know they are adjacent and neither
10405 is zero. */
10406 output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
10407 else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10408 {
10409 ldm[0] = ops[0] = operands[4];
10410 ops[1] = base_reg;
10411 ops[2] = GEN_INT (val1);
10412 output_add_immediate (ops);
10413 if (val1 < val2)
10414 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10415 else
10416 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10417 }
10418 else
10419 {
10420 /* Offset is out of range for a single add, so use two ldr. */
10421 ops[0] = ldm[1];
10422 ops[1] = base_reg;
10423 ops[2] = GEN_INT (val1);
10424 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10425 ops[0] = ldm[2];
10426 ops[2] = GEN_INT (val2);
10427 output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10428 }
10429 }
10430 else if (val1 != 0)
10431 {
10432 if (val1 < val2)
10433 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10434 else
10435 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10436 }
10437 else
10438 {
10439 if (val1 < val2)
10440 output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
10441 else
10442 output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
10443 }
10444 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10445 return \"\";
10446 }"
10447 [(set_attr "length" "12")
10448 (set_attr "predicable" "yes")
10449 (set_attr "type" "load_4")]
10450 )
10451
10452 ; This pattern is never tried by combine, so do it as a peephole
10453
10454 (define_peephole2
10455 [(set (match_operand:SI 0 "arm_general_register_operand" "")
10456 (match_operand:SI 1 "arm_general_register_operand" ""))
10457 (set (reg:CC CC_REGNUM)
10458 (compare:CC (match_dup 1) (const_int 0)))]
10459 "TARGET_ARM"
10460 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10461 (set (match_dup 0) (match_dup 1))])]
10462 ""
10463 )
10464
10465 (define_split
10466 [(set (match_operand:SI 0 "s_register_operand" "")
10467 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10468 (const_int 0))
10469 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10470 [(match_operand:SI 3 "s_register_operand" "")
10471 (match_operand:SI 4 "arm_rhs_operand" "")]))))
10472 (clobber (match_operand:SI 5 "s_register_operand" ""))]
10473 "TARGET_ARM"
10474 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10475 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10476 (match_dup 5)))]
10477 ""
10478 )
10479
10480 ;; This split can be used because CC_Z mode implies that the following
10481 ;; branch will be an equality, or an unsigned inequality, so the sign
10482 ;; extension is not needed.
10483
10484 (define_split
10485 [(set (reg:CC_Z CC_REGNUM)
10486 (compare:CC_Z
10487 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10488 (const_int 24))
10489 (match_operand 1 "const_int_operand" "")))
10490 (clobber (match_scratch:SI 2 ""))]
10491 "TARGET_ARM
10492 && ((UINTVAL (operands[1]))
10493 == ((UINTVAL (operands[1])) >> 24) << 24)"
10494 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10495 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10496 "
10497 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10498 "
10499 )
10500 ;; ??? Check the patterns above for Thumb-2 usefulness
10501
10502 (define_expand "prologue"
10503 [(clobber (const_int 0))]
10504 "TARGET_EITHER"
10505 "if (TARGET_32BIT)
10506 arm_expand_prologue ();
10507 else
10508 thumb1_expand_prologue ();
10509 DONE;
10510 "
10511 )
10512
10513 (define_expand "epilogue"
10514 [(clobber (const_int 0))]
10515 "TARGET_EITHER"
10516 "
10517 if (crtl->calls_eh_return)
10518 emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
10519 if (TARGET_THUMB1)
10520 {
10521 thumb1_expand_epilogue ();
10522 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10523 gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10524 }
10525 else if (HAVE_return)
10526 {
10527 /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10528 no need for explicit testing again. */
10529 emit_jump_insn (gen_return ());
10530 }
10531 else if (TARGET_32BIT)
10532 {
10533 arm_expand_epilogue (true);
10534 }
10535 DONE;
10536 "
10537 )
10538
10539 ;; Note - although unspec_volatile's USE all hard registers,
10540 ;; USEs are ignored after relaod has completed. Thus we need
10541 ;; to add an unspec of the link register to ensure that flow
10542 ;; does not think that it is unused by the sibcall branch that
10543 ;; will replace the standard function epilogue.
10544 (define_expand "sibcall_epilogue"
10545 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
10546 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10547 "TARGET_32BIT"
10548 "
10549 arm_expand_epilogue (false);
10550 DONE;
10551 "
10552 )
10553
10554 (define_expand "eh_epilogue"
10555 [(use (match_operand:SI 0 "register_operand"))
10556 (use (match_operand:SI 1 "register_operand"))
10557 (use (match_operand:SI 2 "register_operand"))]
10558 "TARGET_EITHER"
10559 "
10560 {
10561 cfun->machine->eh_epilogue_sp_ofs = operands[1];
10562 if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
10563 {
10564 rtx ra = gen_rtx_REG (Pmode, 2);
10565
10566 emit_move_insn (ra, operands[2]);
10567 operands[2] = ra;
10568 }
10569 /* This is a hack -- we may have crystalized the function type too
10570 early. */
10571 cfun->machine->func_type = 0;
10572 }"
10573 )
10574
10575 ;; This split is only used during output to reduce the number of patterns
10576 ;; that need assembler instructions adding to them. We allowed the setting
10577 ;; of the conditions to be implicit during rtl generation so that
10578 ;; the conditional compare patterns would work. However this conflicts to
10579 ;; some extent with the conditional data operations, so we have to split them
10580 ;; up again here.
10581
10582 ;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10583 ;; conditional execution sufficient?
10584
10585 (define_split
10586 [(set (match_operand:SI 0 "s_register_operand" "")
10587 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10588 [(match_operand 2 "" "") (match_operand 3 "" "")])
10589 (match_dup 0)
10590 (match_operand 4 "" "")))
10591 (clobber (reg:CC CC_REGNUM))]
10592 "TARGET_ARM && reload_completed"
10593 [(set (match_dup 5) (match_dup 6))
10594 (cond_exec (match_dup 7)
10595 (set (match_dup 0) (match_dup 4)))]
10596 "
10597 {
10598 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10599 operands[2], operands[3]);
10600 enum rtx_code rc = GET_CODE (operands[1]);
10601
10602 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10603 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10604 if (mode == CCFPmode || mode == CCFPEmode)
10605 rc = reverse_condition_maybe_unordered (rc);
10606 else
10607 rc = reverse_condition (rc);
10608
10609 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10610 }"
10611 )
10612
10613 (define_split
10614 [(set (match_operand:SI 0 "s_register_operand" "")
10615 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10616 [(match_operand 2 "" "") (match_operand 3 "" "")])
10617 (match_operand 4 "" "")
10618 (match_dup 0)))
10619 (clobber (reg:CC CC_REGNUM))]
10620 "TARGET_ARM && reload_completed"
10621 [(set (match_dup 5) (match_dup 6))
10622 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10623 (set (match_dup 0) (match_dup 4)))]
10624 "
10625 {
10626 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10627 operands[2], operands[3]);
10628
10629 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10630 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10631 }"
10632 )
10633
10634 (define_split
10635 [(set (match_operand:SI 0 "s_register_operand" "")
10636 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10637 [(match_operand 2 "" "") (match_operand 3 "" "")])
10638 (match_operand 4 "" "")
10639 (match_operand 5 "" "")))
10640 (clobber (reg:CC CC_REGNUM))]
10641 "TARGET_ARM && reload_completed"
10642 [(set (match_dup 6) (match_dup 7))
10643 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10644 (set (match_dup 0) (match_dup 4)))
10645 (cond_exec (match_dup 8)
10646 (set (match_dup 0) (match_dup 5)))]
10647 "
10648 {
10649 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10650 operands[2], operands[3]);
10651 enum rtx_code rc = GET_CODE (operands[1]);
10652
10653 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10654 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10655 if (mode == CCFPmode || mode == CCFPEmode)
10656 rc = reverse_condition_maybe_unordered (rc);
10657 else
10658 rc = reverse_condition (rc);
10659
10660 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10661 }"
10662 )
10663
10664 (define_split
10665 [(set (match_operand:SI 0 "s_register_operand" "")
10666 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10667 [(match_operand:SI 2 "s_register_operand" "")
10668 (match_operand:SI 3 "arm_add_operand" "")])
10669 (match_operand:SI 4 "arm_rhs_operand" "")
10670 (not:SI
10671 (match_operand:SI 5 "s_register_operand" ""))))
10672 (clobber (reg:CC CC_REGNUM))]
10673 "TARGET_ARM && reload_completed"
10674 [(set (match_dup 6) (match_dup 7))
10675 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10676 (set (match_dup 0) (match_dup 4)))
10677 (cond_exec (match_dup 8)
10678 (set (match_dup 0) (not:SI (match_dup 5))))]
10679 "
10680 {
10681 machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10682 operands[2], operands[3]);
10683 enum rtx_code rc = GET_CODE (operands[1]);
10684
10685 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10686 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10687 if (mode == CCFPmode || mode == CCFPEmode)
10688 rc = reverse_condition_maybe_unordered (rc);
10689 else
10690 rc = reverse_condition (rc);
10691
10692 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10693 }"
10694 )
10695
10696 (define_insn "*cond_move_not"
10697 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10698 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10699 [(match_operand 3 "cc_register" "") (const_int 0)])
10700 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10701 (not:SI
10702 (match_operand:SI 2 "s_register_operand" "r,r"))))]
10703 "TARGET_ARM"
10704 "@
10705 mvn%D4\\t%0, %2
10706 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10707 [(set_attr "conds" "use")
10708 (set_attr "type" "mvn_reg,multiple")
10709 (set_attr "length" "4,8")]
10710 )
10711
10712 ;; The next two patterns occur when an AND operation is followed by a
10713 ;; scc insn sequence
10714
10715 (define_insn "*sign_extract_onebit"
10716 [(set (match_operand:SI 0 "s_register_operand" "=r")
10717 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10718 (const_int 1)
10719 (match_operand:SI 2 "const_int_operand" "n")))
10720 (clobber (reg:CC CC_REGNUM))]
10721 "TARGET_ARM"
10722 "*
10723 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10724 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10725 return \"mvnne\\t%0, #0\";
10726 "
10727 [(set_attr "conds" "clob")
10728 (set_attr "length" "8")
10729 (set_attr "type" "multiple")]
10730 )
10731
10732 (define_insn "*not_signextract_onebit"
10733 [(set (match_operand:SI 0 "s_register_operand" "=r")
10734 (not:SI
10735 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10736 (const_int 1)
10737 (match_operand:SI 2 "const_int_operand" "n"))))
10738 (clobber (reg:CC CC_REGNUM))]
10739 "TARGET_ARM"
10740 "*
10741 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10742 output_asm_insn (\"tst\\t%1, %2\", operands);
10743 output_asm_insn (\"mvneq\\t%0, #0\", operands);
10744 return \"movne\\t%0, #0\";
10745 "
10746 [(set_attr "conds" "clob")
10747 (set_attr "length" "12")
10748 (set_attr "type" "multiple")]
10749 )
10750 ;; ??? The above patterns need auditing for Thumb-2
10751
10752 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10753 ;; expressions. For simplicity, the first register is also in the unspec
10754 ;; part.
10755 ;; To avoid the usage of GNU extension, the length attribute is computed
10756 ;; in a C function arm_attr_length_push_multi.
10757 (define_insn "*push_multi"
10758 [(match_parallel 2 "multi_register_push"
10759 [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10760 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10761 UNSPEC_PUSH_MULT))])]
10762 ""
10763 "*
10764 {
10765 int num_saves = XVECLEN (operands[2], 0);
10766
10767 /* For the StrongARM at least it is faster to
10768 use STR to store only a single register.
10769 In Thumb mode always use push, and the assembler will pick
10770 something appropriate. */
10771 if (num_saves == 1 && TARGET_ARM)
10772 output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
10773 else
10774 {
10775 int i;
10776 char pattern[100];
10777
10778 if (TARGET_32BIT)
10779 strcpy (pattern, \"push%?\\t{%1\");
10780 else
10781 strcpy (pattern, \"push\\t{%1\");
10782
10783 for (i = 1; i < num_saves; i++)
10784 {
10785 strcat (pattern, \", %|\");
10786 strcat (pattern,
10787 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10788 }
10789
10790 strcat (pattern, \"}\");
10791 output_asm_insn (pattern, operands);
10792 }
10793
10794 return \"\";
10795 }"
10796 [(set_attr "type" "store_16")
10797 (set (attr "length")
10798 (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
10799 )
10800
10801 (define_insn "stack_tie"
10802 [(set (mem:BLK (scratch))
10803 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10804 (match_operand:SI 1 "s_register_operand" "rk")]
10805 UNSPEC_PRLG_STK))]
10806 ""
10807 ""
10808 [(set_attr "length" "0")
10809 (set_attr "type" "block")]
10810 )
10811
10812 ;; Pop (as used in epilogue RTL)
10813 ;;
10814 (define_insn "*load_multiple_with_writeback"
10815 [(match_parallel 0 "load_multiple_operation"
10816 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10817 (plus:SI (match_dup 1)
10818 (match_operand:SI 2 "const_int_I_operand" "I")))
10819 (set (match_operand:SI 3 "s_register_operand" "=rk")
10820 (mem:SI (match_dup 1)))
10821 ])]
10822 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10823 "*
10824 {
10825 arm_output_multireg_pop (operands, /*return_pc=*/false,
10826 /*cond=*/const_true_rtx,
10827 /*reverse=*/false,
10828 /*update=*/true);
10829 return \"\";
10830 }
10831 "
10832 [(set_attr "type" "load_16")
10833 (set_attr "predicable" "yes")
10834 (set (attr "length")
10835 (symbol_ref "arm_attr_length_pop_multi (operands,
10836 /*return_pc=*/false,
10837 /*write_back_p=*/true)"))]
10838 )
10839
10840 ;; Pop with return (as used in epilogue RTL)
10841 ;;
10842 ;; This instruction is generated when the registers are popped at the end of
10843 ;; epilogue. Here, instead of popping the value into LR and then generating
10844 ;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10845 ;; with (return).
10846 (define_insn "*pop_multiple_with_writeback_and_return"
10847 [(match_parallel 0 "pop_multiple_return"
10848 [(return)
10849 (set (match_operand:SI 1 "s_register_operand" "+rk")
10850 (plus:SI (match_dup 1)
10851 (match_operand:SI 2 "const_int_I_operand" "I")))
10852 (set (match_operand:SI 3 "s_register_operand" "=rk")
10853 (mem:SI (match_dup 1)))
10854 ])]
10855 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10856 "*
10857 {
10858 arm_output_multireg_pop (operands, /*return_pc=*/true,
10859 /*cond=*/const_true_rtx,
10860 /*reverse=*/false,
10861 /*update=*/true);
10862 return \"\";
10863 }
10864 "
10865 [(set_attr "type" "load_16")
10866 (set_attr "predicable" "yes")
10867 (set (attr "length")
10868 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10869 /*write_back_p=*/true)"))]
10870 )
10871
10872 (define_insn "*pop_multiple_with_return"
10873 [(match_parallel 0 "pop_multiple_return"
10874 [(return)
10875 (set (match_operand:SI 2 "s_register_operand" "=rk")
10876 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10877 ])]
10878 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10879 "*
10880 {
10881 arm_output_multireg_pop (operands, /*return_pc=*/true,
10882 /*cond=*/const_true_rtx,
10883 /*reverse=*/false,
10884 /*update=*/false);
10885 return \"\";
10886 }
10887 "
10888 [(set_attr "type" "load_16")
10889 (set_attr "predicable" "yes")
10890 (set (attr "length")
10891 (symbol_ref "arm_attr_length_pop_multi (operands, /*return_pc=*/true,
10892 /*write_back_p=*/false)"))]
10893 )
10894
10895 ;; Load into PC and return
10896 (define_insn "*ldr_with_return"
10897 [(return)
10898 (set (reg:SI PC_REGNUM)
10899 (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10900 "TARGET_32BIT && (reload_in_progress || reload_completed)"
10901 "ldr%?\t%|pc, [%0], #4"
10902 [(set_attr "type" "load_4")
10903 (set_attr "predicable" "yes")]
10904 )
10905 ;; Pop for floating point registers (as used in epilogue RTL)
10906 (define_insn "*vfp_pop_multiple_with_writeback"
10907 [(match_parallel 0 "pop_multiple_fp"
10908 [(set (match_operand:SI 1 "s_register_operand" "+rk")
10909 (plus:SI (match_dup 1)
10910 (match_operand:SI 2 "const_int_I_operand" "I")))
10911 (set (match_operand:DF 3 "vfp_hard_register_operand" "")
10912 (mem:DF (match_dup 1)))])]
10913 "TARGET_32BIT && TARGET_HARD_FLOAT"
10914 "*
10915 {
10916 int num_regs = XVECLEN (operands[0], 0);
10917 char pattern[100];
10918 rtx op_list[2];
10919 strcpy (pattern, \"vldm\\t\");
10920 strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10921 strcat (pattern, \"!, {\");
10922 op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10923 strcat (pattern, \"%P0\");
10924 if ((num_regs - 1) > 1)
10925 {
10926 strcat (pattern, \"-%P1\");
10927 op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10928 }
10929
10930 strcat (pattern, \"}\");
10931 output_asm_insn (pattern, op_list);
10932 return \"\";
10933 }
10934 "
10935 [(set_attr "type" "load_16")
10936 (set_attr "conds" "unconditional")
10937 (set_attr "predicable" "no")]
10938 )
10939
10940 ;; Special patterns for dealing with the constant pool
10941
10942 (define_insn "align_4"
10943 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10944 "TARGET_EITHER"
10945 "*
10946 assemble_align (32);
10947 return \"\";
10948 "
10949 [(set_attr "type" "no_insn")]
10950 )
10951
10952 (define_insn "align_8"
10953 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10954 "TARGET_EITHER"
10955 "*
10956 assemble_align (64);
10957 return \"\";
10958 "
10959 [(set_attr "type" "no_insn")]
10960 )
10961
10962 (define_insn "consttable_end"
10963 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10964 "TARGET_EITHER"
10965 "*
10966 making_const_table = FALSE;
10967 return \"\";
10968 "
10969 [(set_attr "type" "no_insn")]
10970 )
10971
10972 (define_insn "consttable_1"
10973 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10974 "TARGET_EITHER"
10975 "*
10976 making_const_table = TRUE;
10977 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10978 assemble_zeros (3);
10979 return \"\";
10980 "
10981 [(set_attr "length" "4")
10982 (set_attr "type" "no_insn")]
10983 )
10984
10985 (define_insn "consttable_2"
10986 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10987 "TARGET_EITHER"
10988 "*
10989 {
10990 rtx x = operands[0];
10991 making_const_table = TRUE;
10992 switch (GET_MODE_CLASS (GET_MODE (x)))
10993 {
10994 case MODE_FLOAT:
10995 arm_emit_fp16_const (x);
10996 break;
10997 default:
10998 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10999 assemble_zeros (2);
11000 break;
11001 }
11002 return \"\";
11003 }"
11004 [(set_attr "length" "4")
11005 (set_attr "type" "no_insn")]
11006 )
11007
11008 (define_insn "consttable_4"
11009 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
11010 "TARGET_EITHER"
11011 "*
11012 {
11013 rtx x = operands[0];
11014 making_const_table = TRUE;
11015 scalar_float_mode float_mode;
11016 if (is_a <scalar_float_mode> (GET_MODE (x), &float_mode))
11017 assemble_real (*CONST_DOUBLE_REAL_VALUE (x), float_mode, BITS_PER_WORD);
11018 else
11019 {
11020 /* XXX: Sometimes gcc does something really dumb and ends up with
11021 a HIGH in a constant pool entry, usually because it's trying to
11022 load into a VFP register. We know this will always be used in
11023 combination with a LO_SUM which ignores the high bits, so just
11024 strip off the HIGH. */
11025 if (GET_CODE (x) == HIGH)
11026 x = XEXP (x, 0);
11027 assemble_integer (x, 4, BITS_PER_WORD, 1);
11028 mark_symbol_refs_as_used (x);
11029 }
11030 return \"\";
11031 }"
11032 [(set_attr "length" "4")
11033 (set_attr "type" "no_insn")]
11034 )
11035
11036 (define_insn "consttable_8"
11037 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11038 "TARGET_EITHER"
11039 "*
11040 {
11041 making_const_table = TRUE;
11042 scalar_float_mode float_mode;
11043 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11044 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11045 float_mode, BITS_PER_WORD);
11046 else
11047 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11048 return \"\";
11049 }"
11050 [(set_attr "length" "8")
11051 (set_attr "type" "no_insn")]
11052 )
11053
11054 (define_insn "consttable_16"
11055 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11056 "TARGET_EITHER"
11057 "*
11058 {
11059 making_const_table = TRUE;
11060 scalar_float_mode float_mode;
11061 if (is_a <scalar_float_mode> (GET_MODE (operands[0]), &float_mode))
11062 assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
11063 float_mode, BITS_PER_WORD);
11064 else
11065 assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11066 return \"\";
11067 }"
11068 [(set_attr "length" "16")
11069 (set_attr "type" "no_insn")]
11070 )
11071
11072 ;; V5 Instructions,
11073
11074 (define_insn "clzsi2"
11075 [(set (match_operand:SI 0 "s_register_operand" "=r")
11076 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11077 "TARGET_32BIT && arm_arch5t"
11078 "clz%?\\t%0, %1"
11079 [(set_attr "predicable" "yes")
11080 (set_attr "type" "clz")])
11081
11082 (define_insn "rbitsi2"
11083 [(set (match_operand:SI 0 "s_register_operand" "=r")
11084 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11085 "TARGET_32BIT && arm_arch_thumb2"
11086 "rbit%?\\t%0, %1"
11087 [(set_attr "predicable" "yes")
11088 (set_attr "type" "clz")])
11089
11090 ;; Keep this as a CTZ expression until after reload and then split
11091 ;; into RBIT + CLZ. Since RBIT is represented as an UNSPEC it is unlikely
11092 ;; to fold with any other expression.
11093
11094 (define_insn_and_split "ctzsi2"
11095 [(set (match_operand:SI 0 "s_register_operand" "=r")
11096 (ctz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11097 "TARGET_32BIT && arm_arch_thumb2"
11098 "#"
11099 "&& reload_completed"
11100 [(const_int 0)]
11101 "
11102 emit_insn (gen_rbitsi2 (operands[0], operands[1]));
11103 emit_insn (gen_clzsi2 (operands[0], operands[0]));
11104 DONE;
11105 ")
11106
11107 ;; V5E instructions.
11108
11109 (define_insn "prefetch"
11110 [(prefetch (match_operand:SI 0 "address_operand" "p")
11111 (match_operand:SI 1 "" "")
11112 (match_operand:SI 2 "" ""))]
11113 "TARGET_32BIT && arm_arch5te"
11114 "pld\\t%a0"
11115 [(set_attr "type" "load_4")]
11116 )
11117
11118 ;; General predication pattern
11119
11120 (define_cond_exec
11121 [(match_operator 0 "arm_comparison_operator"
11122 [(match_operand 1 "cc_register" "")
11123 (const_int 0)])]
11124 "TARGET_32BIT
11125 && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
11126 ""
11127 [(set_attr "predicated" "yes")]
11128 )
11129
11130 (define_insn "force_register_use"
11131 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
11132 ""
11133 "%@ %0 needed"
11134 [(set_attr "length" "0")
11135 (set_attr "type" "no_insn")]
11136 )
11137
11138
11139 ;; Patterns for exception handling
11140
11141 (define_expand "eh_return"
11142 [(use (match_operand 0 "general_operand"))]
11143 "TARGET_EITHER"
11144 "
11145 {
11146 if (TARGET_32BIT)
11147 emit_insn (gen_arm_eh_return (operands[0]));
11148 else
11149 emit_insn (gen_thumb_eh_return (operands[0]));
11150 DONE;
11151 }"
11152 )
11153
11154 ;; We can't expand this before we know where the link register is stored.
11155 (define_insn_and_split "arm_eh_return"
11156 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11157 VUNSPEC_EH_RETURN)
11158 (clobber (match_scratch:SI 1 "=&r"))]
11159 "TARGET_ARM"
11160 "#"
11161 "&& reload_completed"
11162 [(const_int 0)]
11163 "
11164 {
11165 arm_set_return_address (operands[0], operands[1]);
11166 DONE;
11167 }"
11168 )
11169
11170 \f
11171 ;; TLS support
11172
11173 (define_insn "load_tp_hard"
11174 [(set (match_operand:SI 0 "register_operand" "=r")
11175 (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11176 "TARGET_HARD_TP"
11177 "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11178 [(set_attr "predicable" "yes")
11179 (set_attr "type" "mrs")]
11180 )
11181
11182 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11183 (define_insn "load_tp_soft_fdpic"
11184 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11185 (clobber (reg:SI FDPIC_REGNUM))
11186 (clobber (reg:SI LR_REGNUM))
11187 (clobber (reg:SI IP_REGNUM))
11188 (clobber (reg:CC CC_REGNUM))]
11189 "TARGET_SOFT_TP && TARGET_FDPIC"
11190 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11191 [(set_attr "conds" "clob")
11192 (set_attr "type" "branch")]
11193 )
11194
11195 ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
11196 (define_insn "load_tp_soft"
11197 [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11198 (clobber (reg:SI LR_REGNUM))
11199 (clobber (reg:SI IP_REGNUM))
11200 (clobber (reg:CC CC_REGNUM))]
11201 "TARGET_SOFT_TP && !TARGET_FDPIC"
11202 "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11203 [(set_attr "conds" "clob")
11204 (set_attr "type" "branch")]
11205 )
11206
11207 ;; tls descriptor call
11208 (define_insn "tlscall"
11209 [(set (reg:SI R0_REGNUM)
11210 (unspec:SI [(reg:SI R0_REGNUM)
11211 (match_operand:SI 0 "" "X")
11212 (match_operand 1 "" "")] UNSPEC_TLS))
11213 (clobber (reg:SI R1_REGNUM))
11214 (clobber (reg:SI LR_REGNUM))
11215 (clobber (reg:SI CC_REGNUM))]
11216 "TARGET_GNU2_TLS"
11217 {
11218 targetm.asm_out.internal_label (asm_out_file, "LPIC",
11219 INTVAL (operands[1]));
11220 return "bl\\t%c0(tlscall)";
11221 }
11222 [(set_attr "conds" "clob")
11223 (set_attr "length" "4")
11224 (set_attr "type" "branch")]
11225 )
11226
11227 ;; For thread pointer builtin
11228 (define_expand "get_thread_pointersi"
11229 [(match_operand:SI 0 "s_register_operand")]
11230 ""
11231 "
11232 {
11233 arm_load_tp (operands[0]);
11234 DONE;
11235 }")
11236
11237 ;;
11238
11239 ;; We only care about the lower 16 bits of the constant
11240 ;; being inserted into the upper 16 bits of the register.
11241 (define_insn "*arm_movtas_ze"
11242 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
11243 (const_int 16)
11244 (const_int 16))
11245 (match_operand:SI 1 "const_int_operand" ""))]
11246 "TARGET_HAVE_MOVT"
11247 "@
11248 movt%?\t%0, %L1
11249 movt\t%0, %L1"
11250 [(set_attr "arch" "32,v8mb")
11251 (set_attr "predicable" "yes")
11252 (set_attr "length" "4")
11253 (set_attr "type" "alu_sreg")]
11254 )
11255
11256 (define_insn "*arm_rev"
11257 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11258 (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
11259 "arm_arch6"
11260 "@
11261 rev\t%0, %1
11262 rev%?\t%0, %1
11263 rev%?\t%0, %1"
11264 [(set_attr "arch" "t1,t2,32")
11265 (set_attr "length" "2,2,4")
11266 (set_attr "predicable" "no,yes,yes")
11267 (set_attr "type" "rev")]
11268 )
11269
11270 (define_expand "arm_legacy_rev"
11271 [(set (match_operand:SI 2 "s_register_operand")
11272 (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
11273 (const_int 16))
11274 (match_dup 1)))
11275 (set (match_dup 2)
11276 (lshiftrt:SI (match_dup 2)
11277 (const_int 8)))
11278 (set (match_operand:SI 3 "s_register_operand")
11279 (rotatert:SI (match_dup 1)
11280 (const_int 8)))
11281 (set (match_dup 2)
11282 (and:SI (match_dup 2)
11283 (const_int -65281)))
11284 (set (match_operand:SI 0 "s_register_operand")
11285 (xor:SI (match_dup 3)
11286 (match_dup 2)))]
11287 "TARGET_32BIT"
11288 ""
11289 )
11290
11291 ;; Reuse temporaries to keep register pressure down.
11292 (define_expand "thumb_legacy_rev"
11293 [(set (match_operand:SI 2 "s_register_operand")
11294 (ashift:SI (match_operand:SI 1 "s_register_operand")
11295 (const_int 24)))
11296 (set (match_operand:SI 3 "s_register_operand")
11297 (lshiftrt:SI (match_dup 1)
11298 (const_int 24)))
11299 (set (match_dup 3)
11300 (ior:SI (match_dup 3)
11301 (match_dup 2)))
11302 (set (match_operand:SI 4 "s_register_operand")
11303 (const_int 16))
11304 (set (match_operand:SI 5 "s_register_operand")
11305 (rotatert:SI (match_dup 1)
11306 (match_dup 4)))
11307 (set (match_dup 2)
11308 (ashift:SI (match_dup 5)
11309 (const_int 24)))
11310 (set (match_dup 5)
11311 (lshiftrt:SI (match_dup 5)
11312 (const_int 24)))
11313 (set (match_dup 5)
11314 (ior:SI (match_dup 5)
11315 (match_dup 2)))
11316 (set (match_dup 5)
11317 (rotatert:SI (match_dup 5)
11318 (match_dup 4)))
11319 (set (match_operand:SI 0 "s_register_operand")
11320 (ior:SI (match_dup 5)
11321 (match_dup 3)))]
11322 "TARGET_THUMB"
11323 ""
11324 )
11325
11326 ;; ARM-specific expansion of signed mod by power of 2
11327 ;; using conditional negate.
11328 ;; For r0 % n where n is a power of 2 produce:
11329 ;; rsbs r1, r0, #0
11330 ;; and r0, r0, #(n - 1)
11331 ;; and r1, r1, #(n - 1)
11332 ;; rsbpl r0, r1, #0
11333
11334 (define_expand "modsi3"
11335 [(match_operand:SI 0 "register_operand")
11336 (match_operand:SI 1 "register_operand")
11337 (match_operand:SI 2 "const_int_operand")]
11338 "TARGET_32BIT"
11339 {
11340 HOST_WIDE_INT val = INTVAL (operands[2]);
11341
11342 if (val <= 0
11343 || exact_log2 (val) <= 0)
11344 FAIL;
11345
11346 rtx mask = GEN_INT (val - 1);
11347
11348 /* In the special case of x0 % 2 we can do the even shorter:
11349 cmp r0, #0
11350 and r0, r0, #1
11351 rsblt r0, r0, #0. */
11352
11353 if (val == 2)
11354 {
11355 rtx cc_reg = arm_gen_compare_reg (LT,
11356 operands[1], const0_rtx, NULL_RTX);
11357 rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
11358 rtx masked = gen_reg_rtx (SImode);
11359
11360 emit_insn (gen_andsi3 (masked, operands[1], mask));
11361 emit_move_insn (operands[0],
11362 gen_rtx_IF_THEN_ELSE (SImode, cond,
11363 gen_rtx_NEG (SImode,
11364 masked),
11365 masked));
11366 DONE;
11367 }
11368
11369 rtx neg_op = gen_reg_rtx (SImode);
11370 rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
11371 operands[1]));
11372
11373 /* Extract the condition register and mode. */
11374 rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
11375 rtx cc_reg = SET_DEST (cmp);
11376 rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
11377
11378 emit_insn (gen_andsi3 (operands[0], operands[1], mask));
11379
11380 rtx masked_neg = gen_reg_rtx (SImode);
11381 emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
11382
11383 /* We want a conditional negate here, but emitting COND_EXEC rtxes
11384 during expand does not always work. Do an IF_THEN_ELSE instead. */
11385 emit_move_insn (operands[0],
11386 gen_rtx_IF_THEN_ELSE (SImode, cond,
11387 gen_rtx_NEG (SImode, masked_neg),
11388 operands[0]));
11389
11390
11391 DONE;
11392 }
11393 )
11394
11395 (define_expand "bswapsi2"
11396 [(set (match_operand:SI 0 "s_register_operand")
11397 (bswap:SI (match_operand:SI 1 "s_register_operand")))]
11398 "TARGET_EITHER && (arm_arch6 || !optimize_size)"
11399 "
11400 if (!arm_arch6)
11401 {
11402 rtx op2 = gen_reg_rtx (SImode);
11403 rtx op3 = gen_reg_rtx (SImode);
11404
11405 if (TARGET_THUMB)
11406 {
11407 rtx op4 = gen_reg_rtx (SImode);
11408 rtx op5 = gen_reg_rtx (SImode);
11409
11410 emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11411 op2, op3, op4, op5));
11412 }
11413 else
11414 {
11415 emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11416 op2, op3));
11417 }
11418
11419 DONE;
11420 }
11421 "
11422 )
11423
11424 ;; bswap16 patterns: use revsh and rev16 instructions for the signed
11425 ;; and unsigned variants, respectively. For rev16, expose
11426 ;; byte-swapping in the lower 16 bits only.
11427 (define_insn "*arm_revsh"
11428 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11429 (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11430 "arm_arch6"
11431 "@
11432 revsh\t%0, %1
11433 revsh%?\t%0, %1
11434 revsh%?\t%0, %1"
11435 [(set_attr "arch" "t1,t2,32")
11436 (set_attr "length" "2,2,4")
11437 (set_attr "type" "rev")]
11438 )
11439
11440 (define_insn "*arm_rev16"
11441 [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11442 (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11443 "arm_arch6"
11444 "@
11445 rev16\t%0, %1
11446 rev16%?\t%0, %1
11447 rev16%?\t%0, %1"
11448 [(set_attr "arch" "t1,t2,32")
11449 (set_attr "length" "2,2,4")
11450 (set_attr "type" "rev")]
11451 )
11452
11453 ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11454 ;; operations within an IOR/AND RTX, therefore we have two patterns matching
11455 ;; each valid permutation.
11456
11457 (define_insn "arm_rev16si2"
11458 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11459 (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11460 (const_int 8))
11461 (match_operand:SI 3 "const_int_operand" "n,n,n"))
11462 (and:SI (lshiftrt:SI (match_dup 1)
11463 (const_int 8))
11464 (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11465 "arm_arch6
11466 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11467 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11468 "rev16\\t%0, %1"
11469 [(set_attr "arch" "t1,t2,32")
11470 (set_attr "length" "2,2,4")
11471 (set_attr "type" "rev")]
11472 )
11473
11474 (define_insn "arm_rev16si2_alt"
11475 [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11476 (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11477 (const_int 8))
11478 (match_operand:SI 2 "const_int_operand" "n,n,n"))
11479 (and:SI (ashift:SI (match_dup 1)
11480 (const_int 8))
11481 (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11482 "arm_arch6
11483 && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11484 && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11485 "rev16\\t%0, %1"
11486 [(set_attr "arch" "t1,t2,32")
11487 (set_attr "length" "2,2,4")
11488 (set_attr "type" "rev")]
11489 )
11490
11491 (define_expand "bswaphi2"
11492 [(set (match_operand:HI 0 "s_register_operand")
11493 (bswap:HI (match_operand:HI 1 "s_register_operand")))]
11494 "arm_arch6"
11495 ""
11496 )
11497
11498 ;; Patterns for LDRD/STRD in Thumb2 mode
11499
11500 (define_insn "*thumb2_ldrd"
11501 [(set (match_operand:SI 0 "s_register_operand" "=r")
11502 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11503 (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11504 (set (match_operand:SI 3 "s_register_operand" "=r")
11505 (mem:SI (plus:SI (match_dup 1)
11506 (match_operand:SI 4 "const_int_operand" ""))))]
11507 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11508 && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11509 && (operands_ok_ldrd_strd (operands[0], operands[3],
11510 operands[1], INTVAL (operands[2]),
11511 false, true))"
11512 "ldrd%?\t%0, %3, [%1, %2]"
11513 [(set_attr "type" "load_8")
11514 (set_attr "predicable" "yes")])
11515
11516 (define_insn "*thumb2_ldrd_base"
11517 [(set (match_operand:SI 0 "s_register_operand" "=r")
11518 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11519 (set (match_operand:SI 2 "s_register_operand" "=r")
11520 (mem:SI (plus:SI (match_dup 1)
11521 (const_int 4))))]
11522 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11523 && (operands_ok_ldrd_strd (operands[0], operands[2],
11524 operands[1], 0, false, true))"
11525 "ldrd%?\t%0, %2, [%1]"
11526 [(set_attr "type" "load_8")
11527 (set_attr "predicable" "yes")])
11528
11529 (define_insn "*thumb2_ldrd_base_neg"
11530 [(set (match_operand:SI 0 "s_register_operand" "=r")
11531 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11532 (const_int -4))))
11533 (set (match_operand:SI 2 "s_register_operand" "=r")
11534 (mem:SI (match_dup 1)))]
11535 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11536 && (operands_ok_ldrd_strd (operands[0], operands[2],
11537 operands[1], -4, false, true))"
11538 "ldrd%?\t%0, %2, [%1, #-4]"
11539 [(set_attr "type" "load_8")
11540 (set_attr "predicable" "yes")])
11541
11542 (define_insn "*thumb2_strd"
11543 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11544 (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11545 (match_operand:SI 2 "s_register_operand" "r"))
11546 (set (mem:SI (plus:SI (match_dup 0)
11547 (match_operand:SI 3 "const_int_operand" "")))
11548 (match_operand:SI 4 "s_register_operand" "r"))]
11549 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11550 && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11551 && (operands_ok_ldrd_strd (operands[2], operands[4],
11552 operands[0], INTVAL (operands[1]),
11553 false, false))"
11554 "strd%?\t%2, %4, [%0, %1]"
11555 [(set_attr "type" "store_8")
11556 (set_attr "predicable" "yes")])
11557
11558 (define_insn "*thumb2_strd_base"
11559 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11560 (match_operand:SI 1 "s_register_operand" "r"))
11561 (set (mem:SI (plus:SI (match_dup 0)
11562 (const_int 4)))
11563 (match_operand:SI 2 "s_register_operand" "r"))]
11564 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11565 && (operands_ok_ldrd_strd (operands[1], operands[2],
11566 operands[0], 0, false, false))"
11567 "strd%?\t%1, %2, [%0]"
11568 [(set_attr "type" "store_8")
11569 (set_attr "predicable" "yes")])
11570
11571 (define_insn "*thumb2_strd_base_neg"
11572 [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11573 (const_int -4)))
11574 (match_operand:SI 1 "s_register_operand" "r"))
11575 (set (mem:SI (match_dup 0))
11576 (match_operand:SI 2 "s_register_operand" "r"))]
11577 "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11578 && (operands_ok_ldrd_strd (operands[1], operands[2],
11579 operands[0], -4, false, false))"
11580 "strd%?\t%1, %2, [%0, #-4]"
11581 [(set_attr "type" "store_8")
11582 (set_attr "predicable" "yes")])
11583
11584 ;; ARMv8 CRC32 instructions.
11585 (define_insn "arm_<crc_variant>"
11586 [(set (match_operand:SI 0 "s_register_operand" "=r")
11587 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11588 (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11589 CRC))]
11590 "TARGET_CRC32"
11591 "<crc_variant>\\t%0, %1, %2"
11592 [(set_attr "type" "crc")
11593 (set_attr "conds" "unconditional")]
11594 )
11595
11596 ;; Load the load/store double peephole optimizations.
11597 (include "ldrdstrd.md")
11598
11599 ;; Load the load/store multiple patterns
11600 (include "ldmstm.md")
11601
11602 ;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11603 ;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11604 ;; The operands are validated through the load_multiple_operation
11605 ;; match_parallel predicate rather than through constraints so enable it only
11606 ;; after reload.
11607 (define_insn "*load_multiple"
11608 [(match_parallel 0 "load_multiple_operation"
11609 [(set (match_operand:SI 2 "s_register_operand" "=rk")
11610 (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11611 ])]
11612 "TARGET_32BIT && reload_completed"
11613 "*
11614 {
11615 arm_output_multireg_pop (operands, /*return_pc=*/false,
11616 /*cond=*/const_true_rtx,
11617 /*reverse=*/false,
11618 /*update=*/false);
11619 return \"\";
11620 }
11621 "
11622 [(set_attr "predicable" "yes")]
11623 )
11624
11625 (define_expand "copysignsf3"
11626 [(match_operand:SF 0 "register_operand")
11627 (match_operand:SF 1 "register_operand")
11628 (match_operand:SF 2 "register_operand")]
11629 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11630 "{
11631 emit_move_insn (operands[0], operands[2]);
11632 emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11633 GEN_INT (31), GEN_INT (0),
11634 simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11635 DONE;
11636 }"
11637 )
11638
11639 (define_expand "copysigndf3"
11640 [(match_operand:DF 0 "register_operand")
11641 (match_operand:DF 1 "register_operand")
11642 (match_operand:DF 2 "register_operand")]
11643 "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11644 "{
11645 rtx op0_low = gen_lowpart (SImode, operands[0]);
11646 rtx op0_high = gen_highpart (SImode, operands[0]);
11647 rtx op1_low = gen_lowpart (SImode, operands[1]);
11648 rtx op1_high = gen_highpart (SImode, operands[1]);
11649 rtx op2_high = gen_highpart (SImode, operands[2]);
11650
11651 rtx scratch1 = gen_reg_rtx (SImode);
11652 rtx scratch2 = gen_reg_rtx (SImode);
11653 emit_move_insn (scratch1, op2_high);
11654 emit_move_insn (scratch2, op1_high);
11655
11656 emit_insn(gen_rtx_SET(scratch1,
11657 gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11658 emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11659 emit_move_insn (op0_low, op1_low);
11660 emit_move_insn (op0_high, scratch2);
11661
11662 DONE;
11663 }"
11664 )
11665
11666 ;; movmisalign patterns for HImode and SImode.
11667 (define_expand "movmisalign<mode>"
11668 [(match_operand:HSI 0 "general_operand")
11669 (match_operand:HSI 1 "general_operand")]
11670 "unaligned_access"
11671 {
11672 /* This pattern is not permitted to fail during expansion: if both arguments
11673 are non-registers (e.g. memory := constant), force operand 1 into a
11674 register. */
11675 rtx (* gen_unaligned_load)(rtx, rtx);
11676 rtx tmp_dest = operands[0];
11677 if (!s_register_operand (operands[0], <MODE>mode)
11678 && !s_register_operand (operands[1], <MODE>mode))
11679 operands[1] = force_reg (<MODE>mode, operands[1]);
11680
11681 if (<MODE>mode == HImode)
11682 {
11683 gen_unaligned_load = gen_unaligned_loadhiu;
11684 tmp_dest = gen_reg_rtx (SImode);
11685 }
11686 else
11687 gen_unaligned_load = gen_unaligned_loadsi;
11688
11689 if (MEM_P (operands[1]))
11690 {
11691 emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
11692 if (<MODE>mode == HImode)
11693 emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
11694 }
11695 else
11696 emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
11697
11698 DONE;
11699 })
11700
11701 (define_insn "arm_<cdp>"
11702 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11703 (match_operand:SI 1 "immediate_operand" "n")
11704 (match_operand:SI 2 "immediate_operand" "n")
11705 (match_operand:SI 3 "immediate_operand" "n")
11706 (match_operand:SI 4 "immediate_operand" "n")
11707 (match_operand:SI 5 "immediate_operand" "n")] CDPI)]
11708 "arm_coproc_builtin_available (VUNSPEC_<CDP>)"
11709 {
11710 arm_const_bounds (operands[0], 0, 16);
11711 arm_const_bounds (operands[1], 0, 16);
11712 arm_const_bounds (operands[2], 0, (1 << 5));
11713 arm_const_bounds (operands[3], 0, (1 << 5));
11714 arm_const_bounds (operands[4], 0, (1 << 5));
11715 arm_const_bounds (operands[5], 0, 8);
11716 return "<cdp>\\tp%c0, %1, CR%c2, CR%c3, CR%c4, %5";
11717 }
11718 [(set_attr "length" "4")
11719 (set_attr "type" "coproc")])
11720
11721 (define_insn "*ldc"
11722 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11723 (match_operand:SI 1 "immediate_operand" "n")
11724 (match_operand:SI 2 "memory_operand" "Uz")] LDCI)]
11725 "arm_coproc_builtin_available (VUNSPEC_<LDC>)"
11726 {
11727 arm_const_bounds (operands[0], 0, 16);
11728 arm_const_bounds (operands[1], 0, (1 << 5));
11729 return "<ldc>\\tp%c0, CR%c1, %2";
11730 }
11731 [(set_attr "length" "4")
11732 (set_attr "type" "coproc")])
11733
11734 (define_insn "*stc"
11735 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11736 (match_operand:SI 1 "immediate_operand" "n")
11737 (match_operand:SI 2 "memory_operand" "=Uz")] STCI)]
11738 "arm_coproc_builtin_available (VUNSPEC_<STC>)"
11739 {
11740 arm_const_bounds (operands[0], 0, 16);
11741 arm_const_bounds (operands[1], 0, (1 << 5));
11742 return "<stc>\\tp%c0, CR%c1, %2";
11743 }
11744 [(set_attr "length" "4")
11745 (set_attr "type" "coproc")])
11746
11747 (define_expand "arm_<ldc>"
11748 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11749 (match_operand:SI 1 "immediate_operand")
11750 (mem:SI (match_operand:SI 2 "s_register_operand"))] LDCI)]
11751 "arm_coproc_builtin_available (VUNSPEC_<LDC>)")
11752
11753 (define_expand "arm_<stc>"
11754 [(unspec_volatile [(match_operand:SI 0 "immediate_operand")
11755 (match_operand:SI 1 "immediate_operand")
11756 (mem:SI (match_operand:SI 2 "s_register_operand"))] STCI)]
11757 "arm_coproc_builtin_available (VUNSPEC_<STC>)")
11758
11759 (define_insn "arm_<mcr>"
11760 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11761 (match_operand:SI 1 "immediate_operand" "n")
11762 (match_operand:SI 2 "s_register_operand" "r")
11763 (match_operand:SI 3 "immediate_operand" "n")
11764 (match_operand:SI 4 "immediate_operand" "n")
11765 (match_operand:SI 5 "immediate_operand" "n")] MCRI)
11766 (use (match_dup 2))]
11767 "arm_coproc_builtin_available (VUNSPEC_<MCR>)"
11768 {
11769 arm_const_bounds (operands[0], 0, 16);
11770 arm_const_bounds (operands[1], 0, 8);
11771 arm_const_bounds (operands[3], 0, (1 << 5));
11772 arm_const_bounds (operands[4], 0, (1 << 5));
11773 arm_const_bounds (operands[5], 0, 8);
11774 return "<mcr>\\tp%c0, %1, %2, CR%c3, CR%c4, %5";
11775 }
11776 [(set_attr "length" "4")
11777 (set_attr "type" "coproc")])
11778
11779 (define_insn "arm_<mrc>"
11780 [(set (match_operand:SI 0 "s_register_operand" "=r")
11781 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "n")
11782 (match_operand:SI 2 "immediate_operand" "n")
11783 (match_operand:SI 3 "immediate_operand" "n")
11784 (match_operand:SI 4 "immediate_operand" "n")
11785 (match_operand:SI 5 "immediate_operand" "n")] MRCI))]
11786 "arm_coproc_builtin_available (VUNSPEC_<MRC>)"
11787 {
11788 arm_const_bounds (operands[1], 0, 16);
11789 arm_const_bounds (operands[2], 0, 8);
11790 arm_const_bounds (operands[3], 0, (1 << 5));
11791 arm_const_bounds (operands[4], 0, (1 << 5));
11792 arm_const_bounds (operands[5], 0, 8);
11793 return "<mrc>\\tp%c1, %2, %0, CR%c3, CR%c4, %5";
11794 }
11795 [(set_attr "length" "4")
11796 (set_attr "type" "coproc")])
11797
11798 (define_insn "arm_<mcrr>"
11799 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "n")
11800 (match_operand:SI 1 "immediate_operand" "n")
11801 (match_operand:DI 2 "s_register_operand" "r")
11802 (match_operand:SI 3 "immediate_operand" "n")] MCRRI)
11803 (use (match_dup 2))]
11804 "arm_coproc_builtin_available (VUNSPEC_<MCRR>)"
11805 {
11806 arm_const_bounds (operands[0], 0, 16);
11807 arm_const_bounds (operands[1], 0, 8);
11808 arm_const_bounds (operands[3], 0, (1 << 5));
11809 return "<mcrr>\\tp%c0, %1, %Q2, %R2, CR%c3";
11810 }
11811 [(set_attr "length" "4")
11812 (set_attr "type" "coproc")])
11813
11814 (define_insn "arm_<mrrc>"
11815 [(set (match_operand:DI 0 "s_register_operand" "=r")
11816 (unspec_volatile:DI [(match_operand:SI 1 "immediate_operand" "n")
11817 (match_operand:SI 2 "immediate_operand" "n")
11818 (match_operand:SI 3 "immediate_operand" "n")] MRRCI))]
11819 "arm_coproc_builtin_available (VUNSPEC_<MRRC>)"
11820 {
11821 arm_const_bounds (operands[1], 0, 16);
11822 arm_const_bounds (operands[2], 0, 8);
11823 arm_const_bounds (operands[3], 0, (1 << 5));
11824 return "<mrrc>\\tp%c1, %2, %Q0, %R0, CR%c3";
11825 }
11826 [(set_attr "length" "4")
11827 (set_attr "type" "coproc")])
11828
11829 (define_expand "speculation_barrier"
11830 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11831 "TARGET_EITHER"
11832 "
11833 /* For thumb1 (except Armv8 derivatives), and for pre-Armv7 we don't
11834 have a usable barrier (and probably don't need one in practice).
11835 But to be safe if such code is run on later architectures, call a
11836 helper function in libgcc that will do the thing for the active
11837 system. */
11838 if (!(arm_arch7 || arm_arch8))
11839 {
11840 arm_emit_speculation_barrier_function ();
11841 DONE;
11842 }
11843 "
11844 )
11845
11846 ;; Generate a hard speculation barrier when we have not enabled speculation
11847 ;; tracking.
11848 (define_insn "*speculation_barrier_insn"
11849 [(unspec_volatile [(const_int 0)] VUNSPEC_SPECULATION_BARRIER)]
11850 "arm_arch7 || arm_arch8"
11851 "isb\;dsb\\tsy"
11852 [(set_attr "type" "block")
11853 (set_attr "length" "8")]
11854 )
11855
11856 ;; Vector bits common to IWMMXT and Neon
11857 (include "vec-common.md")
11858 ;; Load the Intel Wireless Multimedia Extension patterns
11859 (include "iwmmxt.md")
11860 ;; Load the VFP co-processor patterns
11861 (include "vfp.md")
11862 ;; Thumb-1 patterns
11863 (include "thumb1.md")
11864 ;; Thumb-2 patterns
11865 (include "thumb2.md")
11866 ;; Neon patterns
11867 (include "neon.md")
11868 ;; Crypto patterns
11869 (include "crypto.md")
11870 ;; Synchronization Primitives
11871 (include "sync.md")
11872 ;; Fixed-point patterns
11873 (include "arm-fixed.md")