1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2018 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery, LLC.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>. */
21 ;; Note: Thumb-2 is the variant of the Thumb architecture that adds
22 ;; 32-bit encodings of [almost all of] the Arm instruction set.
23 ;; Some old documents refer to the relatively minor interworking
24 ;; changes made in armv5t as "thumb2". These are considered part
25 ;; the 16-bit Thumb-1 instruction set.
27 ;; Thumb-2 only allows shift by constant on data processing instructions
28 (define_insn "*thumb_andsi_not_shiftsi_si"
29 [(set (match_operand:SI 0 "s_register_operand" "=r")
30 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
31 [(match_operand:SI 2 "s_register_operand" "r")
32 (match_operand:SI 3 "const_int_operand" "M")]))
33 (match_operand:SI 1 "s_register_operand" "r")))]
35 "bic%?\\t%0, %1, %2%S4"
36 [(set_attr "predicable" "yes")
37 (set_attr "shift" "2")
38 (set_attr "type" "alu_shift_imm")]
41 ;; We use the '0' constraint for operand 1 because reload should
42 ;; be smart enough to generate an appropriate move for the r/r/r case.
43 (define_insn_and_split "*thumb2_smaxsi3"
44 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
45 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
46 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
47 (clobber (reg:CC CC_REGNUM))]
50 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
51 "TARGET_THUMB2 && reload_completed"
52 [(set (reg:CC CC_REGNUM)
53 (compare:CC (match_dup 1) (match_dup 2)))
54 (cond_exec (lt:SI (reg:CC CC_REGNUM) (const_int 0))
58 [(set_attr "conds" "clob")
59 (set_attr "enabled_for_short_it" "yes,yes,no")
60 (set_attr "length" "6,6,10")
61 (set_attr "type" "multiple")]
64 (define_insn_and_split "*thumb2_sminsi3"
65 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
66 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
67 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
68 (clobber (reg:CC CC_REGNUM))]
71 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
72 "TARGET_THUMB2 && reload_completed"
73 [(set (reg:CC CC_REGNUM)
74 (compare:CC (match_dup 1) (match_dup 2)))
75 (cond_exec (ge:SI (reg:CC CC_REGNUM) (const_int 0))
79 [(set_attr "conds" "clob")
80 (set_attr "enabled_for_short_it" "yes,yes,no")
81 (set_attr "length" "6,6,10")
82 (set_attr "type" "multiple")]
85 (define_insn_and_split "*thumb32_umaxsi3"
86 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
87 (umax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
88 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
89 (clobber (reg:CC CC_REGNUM))]
92 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
93 "TARGET_THUMB2 && reload_completed"
94 [(set (reg:CC CC_REGNUM)
95 (compare:CC (match_dup 1) (match_dup 2)))
96 (cond_exec (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
100 [(set_attr "conds" "clob")
101 (set_attr "length" "6,6,10")
102 (set_attr "enabled_for_short_it" "yes,yes,no")
103 (set_attr "type" "multiple")]
106 (define_insn_and_split "*thumb2_uminsi3"
107 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
108 (umin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
109 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
110 (clobber (reg:CC CC_REGNUM))]
113 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
114 "TARGET_THUMB2 && reload_completed"
115 [(set (reg:CC CC_REGNUM)
116 (compare:CC (match_dup 1) (match_dup 2)))
117 (cond_exec (geu:SI (reg:CC CC_REGNUM) (const_int 0))
121 [(set_attr "conds" "clob")
122 (set_attr "length" "6,6,10")
123 (set_attr "enabled_for_short_it" "yes,yes,no")
124 (set_attr "type" "multiple")]
127 (define_insn_and_split "*thumb2_abssi2"
128 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
129 (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0")))
130 (clobber (reg:CC CC_REGNUM))]
133 ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
134 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
135 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
136 "&& reload_completed"
139 if (REGNO(operands[0]) == REGNO(operands[1]))
141 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
143 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
145 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
149 (gen_rtx_SET (operands[0],
150 (gen_rtx_MINUS (SImode,
156 emit_insn (gen_rtx_SET (operands[0],
158 gen_rtx_ASHIFTRT (SImode,
162 emit_insn (gen_rtx_SET (operands[0],
163 gen_rtx_MINUS (SImode,
165 gen_rtx_ASHIFTRT (SImode,
171 [(set_attr "conds" "*,clob,clob")
172 (set_attr "shift" "1")
173 (set_attr "predicable" "yes,no,no")
174 (set_attr "enabled_for_short_it" "yes,yes,no")
175 (set_attr "ce_count" "2")
176 (set_attr "length" "8,6,10")
177 (set_attr "type" "multiple")]
180 (define_insn_and_split "*thumb2_neg_abssi2"
181 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
182 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0"))))
183 (clobber (reg:CC CC_REGNUM))]
186 ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
187 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
188 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
189 "&& reload_completed"
192 if (REGNO(operands[0]) == REGNO(operands[1]))
194 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
196 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
198 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
202 (gen_rtx_SET (operands[0],
203 (gen_rtx_MINUS (SImode,
209 emit_insn (gen_rtx_SET (operands[0],
211 gen_rtx_ASHIFTRT (SImode,
215 emit_insn (gen_rtx_SET (operands[0],
216 gen_rtx_MINUS (SImode,
217 gen_rtx_ASHIFTRT (SImode,
224 [(set_attr "conds" "*,clob,clob")
225 (set_attr "shift" "1")
226 (set_attr "predicable" "yes,no,no")
227 (set_attr "enabled_for_short_it" "yes,yes,no")
228 (set_attr "ce_count" "2")
229 (set_attr "length" "8,6,10")
230 (set_attr "type" "multiple")]
233 ;; Pop a single register as its size is preferred over a post-incremental load
234 (define_insn "*thumb2_pop_single"
235 [(set (match_operand:SI 0 "low_register_operand" "=r")
236 (mem:SI (post_inc:SI (reg:SI SP_REGNUM))))]
237 "TARGET_THUMB2 && (reload_in_progress || reload_completed)"
239 [(set_attr "type" "load_4")
240 (set_attr "length" "2")
241 (set_attr "predicable" "yes")]
244 ;; We have two alternatives here for memory loads (and similarly for stores)
245 ;; to reflect the fact that the permissible constant pool ranges differ
246 ;; between ldr instructions taking low regs and ldr instructions taking high
247 ;; regs. The high register alternatives are not taken into account when
248 ;; choosing register preferences in order to reflect their expense.
249 (define_insn "*thumb2_movsi_insn"
250 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,l ,*hk,m,*m")
251 (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,*mi,l,*hk"))]
252 "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
253 && ( register_operand (operands[0], SImode)
254 || register_operand (operands[1], SImode))"
265 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mvn_imm,mov_imm,load_4,load_4,store_4,store_4")
266 (set_attr "length" "2,4,2,4,4,4,4,4,4")
267 (set_attr "predicable" "yes")
268 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no")
269 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*")
270 (set_attr "neg_pool_range" "*,*,*,*,*,0,0,*,*")]
273 (define_insn "tls_load_dot_plus_four"
274 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
275 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
277 (match_operand 3 "" "")]
279 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
282 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
283 INTVAL (operands[3]));
284 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
286 [(set_attr "length" "4,4,6,6")
287 (set_attr "type" "multiple")]
290 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
291 ;; of the messiness associated with the ARM patterns.
292 (define_insn "*thumb2_movhi_insn"
293 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,l,r,m,r")
294 (match_operand:HI 1 "general_operand" "rk,I,Py,n,r,m"))]
296 && (register_operand (operands[0], HImode)
297 || register_operand (operands[1], HImode))"
299 mov%?\\t%0, %1\\t%@ movhi
300 mov%?\\t%0, %1\\t%@ movhi
301 mov%?\\t%0, %1\\t%@ movhi
302 movw%?\\t%0, %L1\\t%@ movhi
303 strh%?\\t%1, %0\\t%@ movhi
304 ldrh%?\\t%0, %1\\t%@ movhi"
305 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store_4,load_4")
306 (set_attr "predicable" "yes")
307 (set_attr "predicable_short_it" "yes,no,yes,no,no,no")
308 (set_attr "length" "2,4,2,4,4,4")
309 (set_attr "pool_range" "*,*,*,*,*,4094")
310 (set_attr "neg_pool_range" "*,*,*,*,*,250")]
313 (define_insn "*thumb2_storewb_pairsi"
314 [(set (match_operand:SI 0 "register_operand" "=&kr")
315 (plus:SI (match_operand:SI 1 "register_operand" "0")
316 (match_operand:SI 2 "const_int_operand" "n")))
317 (set (mem:SI (plus:SI (match_dup 0) (match_dup 2)))
318 (match_operand:SI 3 "register_operand" "r"))
319 (set (mem:SI (plus:SI (match_dup 0)
320 (match_operand:SI 5 "const_int_operand" "n")))
321 (match_operand:SI 4 "register_operand" "r"))]
323 && INTVAL (operands[5]) == INTVAL (operands[2]) + 4"
324 "strd\\t%3, %4, [%0, %2]!"
325 [(set_attr "type" "store_8")]
328 (define_insn "*thumb2_cmpsi_neg_shiftsi"
329 [(set (reg:CC CC_REGNUM)
330 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
331 (neg:SI (match_operator:SI 3 "shift_operator"
332 [(match_operand:SI 1 "s_register_operand" "r")
333 (match_operand:SI 2 "const_int_operand" "M")]))))]
336 [(set_attr "conds" "set")
337 (set_attr "shift" "1")
338 (set_attr "type" "alus_shift_imm")]
341 (define_insn_and_split "*thumb2_mov_scc"
342 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
343 (match_operator:SI 1 "arm_comparison_operator_mode"
344 [(match_operand 2 "cc_register" "") (const_int 0)]))]
346 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
349 (if_then_else:SI (match_dup 1)
353 [(set_attr "conds" "use")
354 (set_attr "enabled_for_short_it" "yes,no")
355 (set_attr "length" "8,10")
356 (set_attr "type" "multiple")]
359 (define_insn_and_split "*thumb2_mov_negscc"
360 [(set (match_operand:SI 0 "s_register_operand" "=r")
361 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
362 [(match_operand 2 "cc_register" "") (const_int 0)])))]
363 "TARGET_THUMB2 && !arm_restrict_it"
364 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
367 (if_then_else:SI (match_dup 1)
371 operands[3] = GEN_INT (~0);
373 [(set_attr "conds" "use")
374 (set_attr "length" "10")
375 (set_attr "type" "multiple")]
378 (define_insn_and_split "*thumb2_mov_negscc_strict_it"
379 [(set (match_operand:SI 0 "low_register_operand" "=l")
380 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
381 [(match_operand 2 "cc_register" "") (const_int 0)])))]
382 "TARGET_THUMB2 && arm_restrict_it"
383 "#" ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\"
384 "&& reload_completed"
387 (cond_exec (match_dup 4)
391 operands[3] = GEN_INT (~0);
392 machine_mode mode = GET_MODE (operands[2]);
393 enum rtx_code rc = GET_CODE (operands[1]);
395 if (mode == CCFPmode || mode == CCFPEmode)
396 rc = reverse_condition_maybe_unordered (rc);
398 rc = reverse_condition (rc);
399 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
402 [(set_attr "conds" "use")
403 (set_attr "length" "8")
404 (set_attr "type" "multiple")]
407 (define_insn_and_split "*thumb2_mov_notscc"
408 [(set (match_operand:SI 0 "s_register_operand" "=r")
409 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
410 [(match_operand 2 "cc_register" "") (const_int 0)])))]
411 "TARGET_THUMB2 && !arm_restrict_it"
412 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
415 (if_then_else:SI (match_dup 1)
419 operands[3] = GEN_INT (~1);
420 operands[4] = GEN_INT (~0);
422 [(set_attr "conds" "use")
423 (set_attr "length" "10")
424 (set_attr "type" "multiple")]
427 (define_insn_and_split "*thumb2_mov_notscc_strict_it"
428 [(set (match_operand:SI 0 "low_register_operand" "=l")
429 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
430 [(match_operand 2 "cc_register" "") (const_int 0)])))]
431 "TARGET_THUMB2 && arm_restrict_it"
432 "#" ; "mvn %0, #0 ; it%d1 ; lsl%d1 %0, %0, #1"
433 "&& reload_completed"
436 (cond_exec (match_dup 4)
438 (ashift:SI (match_dup 0)
441 operands[3] = GEN_INT (~0);
442 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
443 VOIDmode, operands[2], const0_rtx);
445 [(set_attr "conds" "use")
446 (set_attr "length" "8")
447 (set_attr "type" "multiple")]
450 (define_insn_and_split "*thumb2_movsicc_insn"
451 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r")
453 (match_operator 3 "arm_comparison_operator"
454 [(match_operand 4 "cc_register" "") (const_int 0)])
455 (match_operand:SI 1 "arm_not_operand" "0 ,lPy,0 ,0,rI,K,I ,r,rI,K ,K,r")
456 (match_operand:SI 2 "arm_not_operand" "lPy,0 ,rI,K,0 ,0,rI,I,K ,rI,K,r")))]
459 it\\t%D3\;mov%D3\\t%0, %2
460 it\\t%d3\;mov%d3\\t%0, %1
461 it\\t%D3\;mov%D3\\t%0, %2
462 it\\t%D3\;mvn%D3\\t%0, #%B2
463 it\\t%d3\;mov%d3\\t%0, %1
464 it\\t%d3\;mvn%d3\\t%0, #%B1
471 ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
472 ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
473 ; alt 8: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
474 ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
475 ; alt 10: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
476 ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
477 "&& reload_completed"
480 enum rtx_code rev_code;
484 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
486 gen_rtx_SET (operands[0], operands[1])));
487 rev_code = GET_CODE (operands[3]);
488 mode = GET_MODE (operands[4]);
489 if (mode == CCFPmode || mode == CCFPEmode)
490 rev_code = reverse_condition_maybe_unordered (rev_code);
492 rev_code = reverse_condition (rev_code);
494 rev_cond = gen_rtx_fmt_ee (rev_code,
496 gen_rtx_REG (mode, CC_REGNUM),
498 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
500 gen_rtx_SET (operands[0], operands[2])));
503 [(set_attr "length" "4,4,6,6,6,6,10,8,10,10,10,6")
504 (set_attr "enabled_for_short_it" "yes,yes,no,no,no,no,no,no,no,no,no,yes")
505 (set_attr "conds" "use")
506 (set_attr_alternative "type"
507 [(if_then_else (match_operand 2 "const_int_operand" "")
508 (const_string "mov_imm")
509 (const_string "mov_reg"))
510 (if_then_else (match_operand 1 "const_int_operand" "")
511 (const_string "mov_imm")
512 (const_string "mov_reg"))
513 (if_then_else (match_operand 2 "const_int_operand" "")
514 (const_string "mov_imm")
515 (const_string "mov_reg"))
516 (const_string "mvn_imm")
517 (if_then_else (match_operand 1 "const_int_operand" "")
518 (const_string "mov_imm")
519 (const_string "mov_reg"))
520 (const_string "mvn_imm")
521 (const_string "multiple")
522 (const_string "multiple")
523 (const_string "multiple")
524 (const_string "multiple")
525 (const_string "multiple")
526 (const_string "multiple")])]
529 (define_insn "*thumb2_movsfcc_soft_insn"
530 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
531 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
532 [(match_operand 4 "cc_register" "") (const_int 0)])
533 (match_operand:SF 1 "s_register_operand" "0,r")
534 (match_operand:SF 2 "s_register_operand" "r,0")))]
535 "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
537 it\\t%D3\;mov%D3\\t%0, %2
538 it\\t%d3\;mov%d3\\t%0, %1"
539 [(set_attr "length" "6,6")
540 (set_attr "conds" "use")
541 (set_attr "type" "multiple")]
544 (define_insn "*call_reg_thumb2"
545 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
546 (match_operand 1 "" ""))
547 (use (match_operand 2 "" ""))
548 (clobber (reg:SI LR_REGNUM))]
551 [(set_attr "type" "call")]
554 (define_insn "*nonsecure_call_reg_thumb2"
555 [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
556 UNSPEC_NONSECURE_MEM)
557 (match_operand 0 "" ""))
558 (use (match_operand 1 "" ""))
559 (clobber (reg:SI LR_REGNUM))]
560 "TARGET_THUMB2 && use_cmse"
561 "bl\\t__gnu_cmse_nonsecure_call"
562 [(set_attr "length" "4")
563 (set_attr "type" "call")]
566 (define_insn "*call_value_reg_thumb2"
567 [(set (match_operand 0 "" "")
568 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
569 (match_operand 2 "" "")))
570 (use (match_operand 3 "" ""))
571 (clobber (reg:SI LR_REGNUM))]
574 [(set_attr "type" "call")]
577 (define_insn "*nonsecure_call_value_reg_thumb2"
578 [(set (match_operand 0 "" "")
580 (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
581 UNSPEC_NONSECURE_MEM)
582 (match_operand 1 "" "")))
583 (use (match_operand 2 "" ""))
584 (clobber (reg:SI LR_REGNUM))]
585 "TARGET_THUMB2 && use_cmse"
586 "bl\t__gnu_cmse_nonsecure_call"
587 [(set_attr "length" "4")
588 (set_attr "type" "call")]
591 (define_insn "*thumb2_indirect_jump"
593 (match_operand:SI 0 "register_operand" "l*r"))]
596 [(set_attr "conds" "clob")
597 (set_attr "type" "branch")]
599 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
600 ;; addresses will have the thumb bit set correctly.
603 (define_insn_and_split "*thumb2_and_scc"
604 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
605 (and:SI (match_operator:SI 1 "arm_comparison_operator"
606 [(match_operand 2 "cc_register" "") (const_int 0)])
607 (match_operand:SI 3 "s_register_operand" "r")))]
609 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
610 "&& reload_completed"
612 (and:SI (match_dup 3) (const_int 1)))
613 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
615 machine_mode mode = GET_MODE (operands[2]);
616 enum rtx_code rc = GET_CODE (operands[1]);
618 if (mode == CCFPmode || mode == CCFPEmode)
619 rc = reverse_condition_maybe_unordered (rc);
621 rc = reverse_condition (rc);
622 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
624 [(set_attr "conds" "use")
625 (set_attr "type" "multiple")
626 (set (attr "length") (if_then_else (match_test "arm_restrict_it")
631 (define_insn_and_split "*thumb2_ior_scc"
632 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
633 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
634 [(match_operand 2 "cc_register" "") (const_int 0)])
635 (match_operand:SI 3 "s_register_operand" "0,?r")))]
636 "TARGET_THUMB2 && !arm_restrict_it"
638 it\\t%d1\;orr%d1\\t%0, %3, #1
640 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
642 && REGNO (operands [0]) != REGNO (operands[3])"
643 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
644 (cond_exec (match_dup 4) (set (match_dup 0)
645 (ior:SI (match_dup 3) (const_int 1))))]
647 machine_mode mode = GET_MODE (operands[2]);
648 enum rtx_code rc = GET_CODE (operands[1]);
650 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
651 if (mode == CCFPmode || mode == CCFPEmode)
652 rc = reverse_condition_maybe_unordered (rc);
654 rc = reverse_condition (rc);
655 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
657 [(set_attr "conds" "use")
658 (set_attr "length" "6,10")
659 (set_attr "type" "multiple")]
662 (define_insn_and_split "*thumb2_ior_scc_strict_it"
663 [(set (match_operand:SI 0 "s_register_operand" "=&r")
664 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
665 [(match_operand 3 "cc_register" "") (const_int 0)])
666 (match_operand:SI 1 "s_register_operand" "r")))]
667 "TARGET_THUMB2 && arm_restrict_it"
668 "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
669 "&& reload_completed"
670 [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
671 (cond_exec (match_dup 4)
672 (set (match_dup 0) (match_dup 1)))]
674 machine_mode mode = GET_MODE (operands[3]);
675 rtx_code rc = GET_CODE (operands[2]);
677 if (mode == CCFPmode || mode == CCFPEmode)
678 rc = reverse_condition_maybe_unordered (rc);
680 rc = reverse_condition (rc);
681 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
683 [(set_attr "conds" "use")
684 (set_attr "length" "8")
685 (set_attr "type" "multiple")]
688 (define_insn "*thumb2_cond_move"
689 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
690 (if_then_else:SI (match_operator 3 "equality_operator"
691 [(match_operator 4 "arm_comparison_operator"
692 [(match_operand 5 "cc_register" "") (const_int 0)])
694 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
695 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
698 if (GET_CODE (operands[3]) == NE)
700 if (which_alternative != 1)
701 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
702 if (which_alternative != 0)
703 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
706 switch (which_alternative)
709 output_asm_insn (\"it\\t%d4\", operands);
712 output_asm_insn (\"it\\t%D4\", operands);
716 output_asm_insn (\"it\\t%D4\", operands);
718 output_asm_insn (\"ite\\t%D4\", operands);
723 if (which_alternative != 0)
725 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
726 if (arm_restrict_it && which_alternative == 2)
727 output_asm_insn (\"it\\t%d4\", operands);
729 if (which_alternative != 1)
730 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
733 [(set_attr "conds" "use")
734 (set_attr "length" "6,6,10")
735 (set_attr "type" "multiple")]
738 (define_insn "*thumb2_cond_arith"
739 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
740 (match_operator:SI 5 "shiftable_operator"
741 [(match_operator:SI 4 "arm_comparison_operator"
742 [(match_operand:SI 2 "s_register_operand" "r,r")
743 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
744 (match_operand:SI 1 "s_register_operand" "0,?r")]))
745 (clobber (reg:CC CC_REGNUM))]
746 "TARGET_THUMB2 && !arm_restrict_it"
748 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
749 return \"%i5\\t%0, %1, %2, lsr #31\";
751 output_asm_insn (\"cmp\\t%2, %3\", operands);
752 if (GET_CODE (operands[5]) == AND)
754 output_asm_insn (\"ite\\t%D4\", operands);
755 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
757 else if (GET_CODE (operands[5]) == MINUS)
759 output_asm_insn (\"ite\\t%D4\", operands);
760 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
762 else if (which_alternative != 0)
764 output_asm_insn (\"ite\\t%D4\", operands);
765 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
768 output_asm_insn (\"it\\t%d4\", operands);
769 return \"%i5%d4\\t%0, %1, #1\";
771 [(set_attr "conds" "clob")
772 (set_attr "length" "14")
773 (set_attr "type" "multiple")]
776 (define_insn_and_split "*thumb2_cond_arith_strict_it"
777 [(set (match_operand:SI 0 "s_register_operand" "=l")
778 (match_operator:SI 5 "shiftable_operator_strict_it"
779 [(match_operator:SI 4 "arm_comparison_operator"
780 [(match_operand:SI 2 "s_register_operand" "r")
781 (match_operand:SI 3 "arm_rhs_operand" "rI")])
782 (match_operand:SI 1 "s_register_operand" "0")]))
783 (clobber (reg:CC CC_REGNUM))]
784 "TARGET_THUMB2 && arm_restrict_it"
786 "&& reload_completed"
789 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
791 /* %i5 %0, %1, %2, lsr #31 */
792 rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
795 switch (GET_CODE (operands[5]))
798 op = gen_rtx_AND (SImode, shifted_op, operands[1]);
801 op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
803 default: gcc_unreachable ();
805 emit_insn (gen_rtx_SET (operands[0], op));
810 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
811 gen_rtx_COMPARE (CCmode, operands[2],
814 if (GET_CODE (operands[5]) == AND)
819 enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
820 emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
822 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
823 gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
824 gen_rtx_SET (operands[0], const0_rtx)));
830 %i5%d4\\t%0, %1, #1 */
831 emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
833 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
834 gen_rtx_SET (operands[0],
835 gen_rtx_PLUS (SImode,
842 [(set_attr "conds" "clob")
843 (set_attr "length" "12")
844 (set_attr "type" "multiple")]
847 (define_insn "*thumb2_cond_sub"
848 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
849 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
850 (match_operator:SI 4 "arm_comparison_operator"
851 [(match_operand:SI 2 "s_register_operand" "r,r")
852 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
853 (clobber (reg:CC CC_REGNUM))]
856 output_asm_insn (\"cmp\\t%2, %3\", operands);
857 if (which_alternative != 0)
861 output_asm_insn (\"mov\\t%0, %1\", operands);
862 output_asm_insn (\"it\\t%d4\", operands);
866 output_asm_insn (\"ite\\t%D4\", operands);
867 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
871 output_asm_insn (\"it\\t%d4\", operands);
872 return \"sub%d4\\t%0, %1, #1\";
874 [(set_attr "conds" "clob")
875 (set_attr "length" "10,14")
876 (set_attr "type" "multiple")]
879 (define_insn_and_split "*thumb2_negscc"
880 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
881 (neg:SI (match_operator 3 "arm_comparison_operator"
882 [(match_operand:SI 1 "s_register_operand" "r")
883 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
884 (clobber (reg:CC CC_REGNUM))]
887 "&& reload_completed"
890 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
892 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
894 /* Emit asr\\t%0, %1, #31 */
895 emit_insn (gen_rtx_SET (operands[0],
896 gen_rtx_ASHIFTRT (SImode,
901 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
903 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
904 if (CONST_INT_P (operands[2]))
905 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
906 GEN_INT (- INTVAL (operands[2]))));
908 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
910 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
914 gen_rtx_SET (operands[0],
920 /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
921 enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
922 machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
923 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
925 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
928 emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
930 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
935 gen_rtx_SET (operands[0], const0_rtx)));
940 [(set_attr "conds" "clob")
941 (set_attr "length" "14")
942 (set_attr "type" "multiple")]
945 (define_insn "*thumb2_movcond"
946 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
948 (match_operator 5 "arm_comparison_operator"
949 [(match_operand:SI 3 "s_register_operand" "r,r,r")
950 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
951 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
952 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
953 (clobber (reg:CC CC_REGNUM))]
956 if (GET_CODE (operands[5]) == LT
957 && (operands[4] == const0_rtx))
959 if (which_alternative != 1 && REG_P (operands[1]))
961 if (operands[2] == const0_rtx)
962 return \"and\\t%0, %1, %3, asr #31\";
963 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
965 else if (which_alternative != 0 && REG_P (operands[2]))
967 if (operands[1] == const0_rtx)
968 return \"bic\\t%0, %2, %3, asr #31\";
969 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
971 /* The only case that falls through to here is when both ops 1 & 2
975 if (GET_CODE (operands[5]) == GE
976 && (operands[4] == const0_rtx))
978 if (which_alternative != 1 && REG_P (operands[1]))
980 if (operands[2] == const0_rtx)
981 return \"bic\\t%0, %1, %3, asr #31\";
982 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
984 else if (which_alternative != 0 && REG_P (operands[2]))
986 if (operands[1] == const0_rtx)
987 return \"and\\t%0, %2, %3, asr #31\";
988 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
990 /* The only case that falls through to here is when both ops 1 & 2
993 if (CONST_INT_P (operands[4])
994 && !const_ok_for_arm (INTVAL (operands[4])))
995 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
997 output_asm_insn (\"cmp\\t%3, %4\", operands);
998 switch (which_alternative)
1001 output_asm_insn (\"it\\t%D5\", operands);
1004 output_asm_insn (\"it\\t%d5\", operands);
1007 if (arm_restrict_it)
1009 output_asm_insn (\"mov\\t%0, %1\", operands);
1010 output_asm_insn (\"it\\t%D5\", operands);
1013 output_asm_insn (\"ite\\t%d5\", operands);
1018 if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1019 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1020 if (which_alternative != 1)
1021 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1024 [(set_attr "conds" "clob")
1025 (set_attr "length" "10,10,14")
1026 (set_attr "type" "multiple")]
1029 ;; Zero and sign extension instructions.
1031 ;; All supported Thumb2 implementations are armv6, so only that case is
1033 (define_insn "*thumb2_extendqisi_v6"
1034 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1035 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1036 "TARGET_THUMB2 && arm_arch6"
1040 [(set_attr "type" "extend,load_byte")
1041 (set_attr "predicable" "yes")
1042 (set_attr "pool_range" "*,4094")
1043 (set_attr "neg_pool_range" "*,250")]
1046 (define_insn "*thumb2_zero_extendhisi2_v6"
1047 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1048 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1049 "TARGET_THUMB2 && arm_arch6"
1053 [(set_attr "type" "extend,load_byte")
1054 (set_attr "predicable" "yes")
1055 (set_attr "pool_range" "*,4094")
1056 (set_attr "neg_pool_range" "*,250")]
1059 (define_insn "thumb2_zero_extendqisi2_v6"
1060 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1061 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1062 "TARGET_THUMB2 && arm_arch6"
1065 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1066 [(set_attr "type" "extend,load_byte")
1067 (set_attr "predicable" "yes")
1068 (set_attr "pool_range" "*,4094")
1069 (set_attr "neg_pool_range" "*,250")]
1072 (define_insn "thumb2_casesi_internal"
1073 [(parallel [(set (pc)
1075 (leu (match_operand:SI 0 "s_register_operand" "r")
1076 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1077 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1078 (label_ref (match_operand 2 "" ""))))
1079 (label_ref (match_operand 3 "" ""))))
1080 (clobber (reg:CC CC_REGNUM))
1081 (clobber (match_scratch:SI 4 "=&r"))
1082 (use (label_ref (match_dup 2)))])]
1083 "TARGET_THUMB2 && !flag_pic"
1084 "* return thumb2_output_casesi(operands);"
1085 [(set_attr "conds" "clob")
1086 (set_attr "length" "16")
1087 (set_attr "type" "multiple")]
1090 (define_insn "thumb2_casesi_internal_pic"
1091 [(parallel [(set (pc)
1093 (leu (match_operand:SI 0 "s_register_operand" "r")
1094 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1095 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1096 (label_ref (match_operand 2 "" ""))))
1097 (label_ref (match_operand 3 "" ""))))
1098 (clobber (reg:CC CC_REGNUM))
1099 (clobber (match_scratch:SI 4 "=&r"))
1100 (clobber (match_scratch:SI 5 "=r"))
1101 (use (label_ref (match_dup 2)))])]
1102 "TARGET_THUMB2 && flag_pic"
1103 "* return thumb2_output_casesi(operands);"
1104 [(set_attr "conds" "clob")
1105 (set_attr "length" "20")
1106 (set_attr "type" "multiple")]
1109 (define_insn "*thumb2_return"
1111 "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1112 "* return output_return_instruction (const_true_rtx, true, false, true);"
1113 [(set_attr "type" "branch")
1114 (set_attr "length" "4")]
1117 (define_insn "*thumb2_cmse_entry_return"
1119 "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1120 "* return output_return_instruction (const_true_rtx, true, false, true);"
1121 [(set_attr "type" "branch")
1122 ; This is a return from a cmse_nonsecure_entry function so code will be
1123 ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1124 ; we adapt the length accordingly.
1125 (set (attr "length")
1126 (if_then_else (match_test "TARGET_HARD_FLOAT")
1129 ; We do not support predicate execution of returns from cmse_nonsecure_entry
1130 ; functions because we need to clear the APSR. Since predicable has to be
1131 ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1133 (set_attr "predicable" "no")]
1136 (define_insn_and_split "thumb2_eh_return"
1137 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1139 (clobber (match_scratch:SI 1 "=&r"))]
1142 "&& reload_completed"
1146 thumb_set_return_address (operands[0], operands[1]);
1151 (define_insn "*thumb2_alusi3_short"
1152 [(set (match_operand:SI 0 "s_register_operand" "=l")
1153 (match_operator:SI 3 "thumb_16bit_operator"
1154 [(match_operand:SI 1 "s_register_operand" "0")
1155 (match_operand:SI 2 "s_register_operand" "l")]))
1156 (clobber (reg:CC CC_REGNUM))]
1157 "TARGET_THUMB2 && reload_completed
1158 && GET_CODE(operands[3]) != PLUS
1159 && GET_CODE(operands[3]) != MINUS"
1160 "%I3%!\\t%0, %1, %2"
1161 [(set_attr "predicable" "yes")
1162 (set_attr "length" "2")
1163 (set_attr "type" "alu_sreg")]
1166 (define_insn "*thumb2_shiftsi3_short"
1167 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1168 (match_operator:SI 3 "shift_operator"
1169 [(match_operand:SI 1 "low_register_operand" "0,l")
1170 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1171 (clobber (reg:CC CC_REGNUM))]
1172 "TARGET_THUMB2 && reload_completed
1173 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1174 || REG_P (operands[2]))"
1175 "* return arm_output_shift(operands, 2);"
1176 [(set_attr "predicable" "yes")
1177 (set_attr "shift" "1")
1178 (set_attr "length" "2")
1179 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1180 (const_string "alu_shift_imm")
1181 (const_string "alu_shift_reg")))]
1184 (define_insn "*thumb2_mov<mode>_shortim"
1185 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1186 (match_operand:QHSI 1 "const_int_operand" "I"))
1187 (clobber (reg:CC CC_REGNUM))]
1188 "TARGET_THUMB2 && reload_completed"
1190 [(set_attr "predicable" "yes")
1191 (set_attr "length" "2")
1192 (set_attr "type" "mov_imm")]
1195 (define_insn "*thumb2_addsi_short"
1196 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1197 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1198 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1199 (clobber (reg:CC CC_REGNUM))]
1200 "TARGET_THUMB2 && reload_completed"
1204 if (CONST_INT_P (operands[2]))
1205 val = INTVAL(operands[2]);
1209 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
1210 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1211 return \"sub%!\\t%0, %1, #%n2\";
1213 return \"add%!\\t%0, %1, %2\";
1215 [(set_attr "predicable" "yes")
1216 (set_attr "length" "2")
1217 (set_attr_alternative "type"
1218 [(if_then_else (match_operand 2 "const_int_operand" "")
1219 (const_string "alu_imm")
1220 (const_string "alu_sreg"))
1221 (const_string "alu_imm")])]
1224 (define_insn "*thumb2_subsi_short"
1225 [(set (match_operand:SI 0 "low_register_operand" "=l")
1226 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1227 (match_operand:SI 2 "low_register_operand" "l")))
1228 (clobber (reg:CC CC_REGNUM))]
1229 "TARGET_THUMB2 && reload_completed"
1230 "sub%!\\t%0, %1, %2"
1231 [(set_attr "predicable" "yes")
1232 (set_attr "length" "2")
1233 (set_attr "type" "alu_sreg")]
1237 [(set (match_operand:CC 0 "cc_register" "")
1238 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1239 (match_operand:SI 2 "const_int_operand" "")))]
1241 && peep2_reg_dead_p (1, operands[1])
1242 && satisfies_constraint_Pw (operands[2])"
1244 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1245 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1246 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1250 [(match_scratch:SI 3 "l")
1251 (set (match_operand:CC 0 "cc_register" "")
1252 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1253 (match_operand:SI 2 "const_int_operand" "")))]
1255 && satisfies_constraint_Px (operands[2])"
1257 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1258 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1259 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1262 (define_insn "thumb2_addsi3_compare0"
1263 [(set (reg:CC_NOOV CC_REGNUM)
1265 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1266 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1268 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1269 (plus:SI (match_dup 1) (match_dup 2)))]
1274 if (CONST_INT_P (operands[2]))
1275 val = INTVAL (operands[2]);
1279 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1280 return \"subs\\t%0, %1, #%n2\";
1282 return \"adds\\t%0, %1, %2\";
1284 [(set_attr "conds" "set")
1285 (set_attr "length" "2,2,4")
1286 (set_attr_alternative "type"
1287 [(if_then_else (match_operand 2 "const_int_operand" "")
1288 (const_string "alus_imm")
1289 (const_string "alus_sreg"))
1290 (const_string "alus_imm")
1291 (if_then_else (match_operand 2 "const_int_operand" "")
1292 (const_string "alus_imm")
1293 (const_string "alus_sreg"))])]
1296 (define_insn "*thumb2_addsi3_compare0_scratch"
1297 [(set (reg:CC_NOOV CC_REGNUM)
1299 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r")
1300 (match_operand:SI 1 "arm_add_operand" "lPv,rIL"))
1306 if (CONST_INT_P (operands[1]))
1307 val = INTVAL (operands[1]);
1311 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1312 return \"cmp\\t%0, #%n1\";
1314 return \"cmn\\t%0, %1\";
1316 [(set_attr "conds" "set")
1317 (set_attr "length" "2,4")
1318 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1319 (const_string "alus_imm")
1320 (const_string "alus_sreg")))]
1323 (define_insn "*thumb2_mulsi_short"
1324 [(set (match_operand:SI 0 "low_register_operand" "=l")
1325 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1326 (match_operand:SI 2 "low_register_operand" "l")))
1327 (clobber (reg:CC CC_REGNUM))]
1328 "TARGET_THUMB2 && optimize_size && reload_completed"
1329 "mul%!\\t%0, %2, %0"
1330 [(set_attr "predicable" "yes")
1331 (set_attr "length" "2")
1332 (set_attr "type" "muls")])
1334 (define_insn "*thumb2_mulsi_short_compare0"
1335 [(set (reg:CC_NOOV CC_REGNUM)
1337 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1338 (match_operand:SI 2 "register_operand" "l"))
1340 (set (match_operand:SI 0 "register_operand" "=l")
1341 (mult:SI (match_dup 1) (match_dup 2)))]
1342 "TARGET_THUMB2 && optimize_size"
1344 [(set_attr "length" "2")
1345 (set_attr "type" "muls")])
1347 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1348 [(set (reg:CC_NOOV CC_REGNUM)
1350 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1351 (match_operand:SI 2 "register_operand" "l"))
1353 (clobber (match_scratch:SI 0 "=l"))]
1354 "TARGET_THUMB2 && optimize_size"
1356 [(set_attr "length" "2")
1357 (set_attr "type" "muls")])
1359 (define_insn "*thumb2_cbz"
1360 [(set (pc) (if_then_else
1361 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1363 (label_ref (match_operand 1 "" ""))
1365 (clobber (reg:CC CC_REGNUM))]
1368 if (get_attr_length (insn) == 2)
1369 return \"cbz\\t%0, %l1\";
1371 return \"cmp\\t%0, #0\;beq\\t%l1\";
1373 [(set (attr "length")
1375 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1376 (le (minus (match_dup 1) (pc)) (const_int 128))
1377 (not (match_test "which_alternative")))
1380 (set_attr "type" "branch,multiple")]
1383 (define_insn "*thumb2_cbnz"
1384 [(set (pc) (if_then_else
1385 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1387 (label_ref (match_operand 1 "" ""))
1389 (clobber (reg:CC CC_REGNUM))]
1392 if (get_attr_length (insn) == 2)
1393 return \"cbnz\\t%0, %l1\";
1395 return \"cmp\\t%0, #0\;bne\\t%l1\";
1397 [(set (attr "length")
1399 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1400 (le (minus (match_dup 1) (pc)) (const_int 128))
1401 (not (match_test "which_alternative")))
1404 (set_attr "type" "branch,multiple")]
1407 (define_insn "*thumb2_one_cmplsi2_short"
1408 [(set (match_operand:SI 0 "low_register_operand" "=l")
1409 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1410 (clobber (reg:CC CC_REGNUM))]
1411 "TARGET_THUMB2 && reload_completed"
1413 [(set_attr "predicable" "yes")
1414 (set_attr "length" "2")
1415 (set_attr "type" "mvn_reg")]
1418 (define_insn "*thumb2_negsi2_short"
1419 [(set (match_operand:SI 0 "low_register_operand" "=l")
1420 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1421 (clobber (reg:CC CC_REGNUM))]
1422 "TARGET_THUMB2 && reload_completed"
1424 [(set_attr "predicable" "yes")
1425 (set_attr "length" "2")
1426 (set_attr "type" "alu_sreg")]
1429 ; Constants for op 2 will never be given to these patterns.
1430 (define_insn_and_split "*iordi_notdi_di"
1431 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1432 (ior:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
1433 (match_operand:DI 2 "s_register_operand" "r,0")))]
1436 "TARGET_THUMB2 && reload_completed"
1437 [(set (match_dup 0) (ior:SI (not:SI (match_dup 1)) (match_dup 2)))
1438 (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
1441 operands[3] = gen_highpart (SImode, operands[0]);
1442 operands[0] = gen_lowpart (SImode, operands[0]);
1443 operands[4] = gen_highpart (SImode, operands[1]);
1444 operands[1] = gen_lowpart (SImode, operands[1]);
1445 operands[5] = gen_highpart (SImode, operands[2]);
1446 operands[2] = gen_lowpart (SImode, operands[2]);
1448 [(set_attr "length" "8")
1449 (set_attr "predicable" "yes")
1450 (set_attr "predicable_short_it" "no")
1451 (set_attr "type" "multiple")]
1454 (define_insn_and_split "*iordi_notzesidi_di"
1455 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1456 (ior:DI (not:DI (zero_extend:DI
1457 (match_operand:SI 2 "s_register_operand" "r,r")))
1458 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1461 ; (not (zero_extend...)) means operand0 will always be 0xffffffff
1462 "TARGET_THUMB2 && reload_completed"
1463 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1464 (set (match_dup 3) (const_int -1))]
1467 operands[3] = gen_highpart (SImode, operands[0]);
1468 operands[0] = gen_lowpart (SImode, operands[0]);
1469 operands[1] = gen_lowpart (SImode, operands[1]);
1471 [(set_attr "length" "4,8")
1472 (set_attr "predicable" "yes")
1473 (set_attr "predicable_short_it" "no")
1474 (set_attr "type" "multiple")]
1477 (define_insn_and_split "*iordi_notdi_zesidi"
1478 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1479 (ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "0,?r"))
1481 (match_operand:SI 1 "s_register_operand" "r,r"))))]
1484 "TARGET_THUMB2 && reload_completed"
1485 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1486 (set (match_dup 3) (not:SI (match_dup 4)))]
1489 operands[3] = gen_highpart (SImode, operands[0]);
1490 operands[0] = gen_lowpart (SImode, operands[0]);
1491 operands[1] = gen_lowpart (SImode, operands[1]);
1492 operands[4] = gen_highpart (SImode, operands[2]);
1493 operands[2] = gen_lowpart (SImode, operands[2]);
1495 [(set_attr "length" "8")
1496 (set_attr "predicable" "yes")
1497 (set_attr "predicable_short_it" "no")
1498 (set_attr "type" "multiple")]
1501 (define_insn_and_split "*iordi_notsesidi_di"
1502 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1503 (ior:DI (not:DI (sign_extend:DI
1504 (match_operand:SI 2 "s_register_operand" "r,r")))
1505 (match_operand:DI 1 "s_register_operand" "0,r")))]
1508 "TARGET_THUMB2 && reload_completed"
1509 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1510 (set (match_dup 3) (ior:SI (not:SI
1511 (ashiftrt:SI (match_dup 2) (const_int 31)))
1515 operands[3] = gen_highpart (SImode, operands[0]);
1516 operands[0] = gen_lowpart (SImode, operands[0]);
1517 operands[4] = gen_highpart (SImode, operands[1]);
1518 operands[1] = gen_lowpart (SImode, operands[1]);
1520 [(set_attr "length" "8")
1521 (set_attr "predicable" "yes")
1522 (set_attr "predicable_short_it" "no")
1523 (set_attr "type" "multiple")]
1526 (define_insn "*orsi_notsi_si"
1527 [(set (match_operand:SI 0 "s_register_operand" "=r")
1528 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1529 (match_operand:SI 1 "s_register_operand" "r")))]
1531 "orn%?\\t%0, %1, %2"
1532 [(set_attr "predicable" "yes")
1533 (set_attr "type" "logic_reg")]
1536 (define_insn "*orsi_not_shiftsi_si"
1537 [(set (match_operand:SI 0 "s_register_operand" "=r")
1538 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1539 [(match_operand:SI 2 "s_register_operand" "r")
1540 (match_operand:SI 3 "const_int_operand" "M")]))
1541 (match_operand:SI 1 "s_register_operand" "r")))]
1543 "orn%?\\t%0, %1, %2%S4"
1544 [(set_attr "predicable" "yes")
1545 (set_attr "shift" "2")
1546 (set_attr "type" "alu_shift_imm")]
1550 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1551 (compare:CC_NOOV (zero_extract:SI
1552 (match_operand:SI 1 "low_register_operand" "")
1554 (match_operand:SI 2 "const_int_operand" ""))
1556 (match_scratch:SI 3 "l")
1558 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1559 [(match_dup 0) (const_int 0)])
1560 (match_operand 5 "" "")
1561 (match_operand 6 "" "")))]
1563 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1564 && peep2_reg_dead_p (2, operands[0])"
1565 [(parallel [(set (match_dup 0)
1566 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1568 (clobber (match_dup 3))])
1570 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1571 (match_dup 5) (match_dup 6)))]
1573 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1574 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1575 VOIDmode, operands[0], const0_rtx);
1579 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1580 (compare:CC_NOOV (zero_extract:SI
1581 (match_operand:SI 1 "low_register_operand" "")
1582 (match_operand:SI 2 "const_int_operand" "")
1585 (match_scratch:SI 3 "l")
1587 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1588 [(match_dup 0) (const_int 0)])
1589 (match_operand 5 "" "")
1590 (match_operand 6 "" "")))]
1592 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1593 && peep2_reg_dead_p (2, operands[0])"
1594 [(parallel [(set (match_dup 0)
1595 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1597 (clobber (match_dup 3))])
1599 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1600 (match_dup 5) (match_dup 6)))]
1602 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1605 ;; Define the subtract-one-and-jump insns so loop.c
1606 ;; knows what to generate.
1607 (define_expand "doloop_end"
1608 [(use (match_operand 0 "" "")) ; loop pseudo
1609 (use (match_operand 1 "" ""))] ; label
1613 /* Currently SMS relies on the do-loop pattern to recognize loops
1614 where (1) the control part consists of all insns defining and/or
1615 using a certain 'count' register and (2) the loop count can be
1616 adjusted by modifying this register prior to the loop.
1617 ??? The possible introduction of a new block to initialize the
1618 new IV can potentially affect branch optimizations. */
1619 if (optimize > 0 && flag_modulo_sched)
1628 if (GET_MODE (operands[0]) != SImode)
1633 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1635 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1637 cmp = XVECEXP (PATTERN (insn), 0, 0);
1638 cc_reg = SET_DEST (cmp);
1639 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1640 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1641 emit_jump_insn (gen_rtx_SET (pc_rtx,
1642 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,