1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2021 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 ;; We use the '0' constraint for operand 1 because reload should
28 ;; be smart enough to generate an appropriate move for the r/r/r case.
29 (define_insn_and_split "*thumb2_smaxsi3"
30 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
31 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
32 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
33 (clobber (reg:CC CC_REGNUM))]
36 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
37 "TARGET_THUMB2 && reload_completed"
38 [(set (reg:CC CC_REGNUM)
39 (compare:CC (match_dup 1) (match_dup 2)))
40 (cond_exec (lt:SI (reg:CC CC_REGNUM) (const_int 0))
44 [(set_attr "conds" "clob")
45 (set_attr "enabled_for_short_it" "yes,yes,no")
46 (set_attr "length" "6,6,10")
47 (set_attr "type" "multiple")]
50 (define_insn_and_split "*thumb2_sminsi3"
51 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
52 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
53 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
54 (clobber (reg:CC CC_REGNUM))]
57 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
58 "TARGET_THUMB2 && reload_completed"
59 [(set (reg:CC CC_REGNUM)
60 (compare:CC (match_dup 1) (match_dup 2)))
61 (cond_exec (ge:SI (reg:CC CC_REGNUM) (const_int 0))
65 [(set_attr "conds" "clob")
66 (set_attr "enabled_for_short_it" "yes,yes,no")
67 (set_attr "length" "6,6,10")
68 (set_attr "type" "multiple")]
71 (define_insn_and_split "*thumb32_umaxsi3"
72 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
73 (umax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
74 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
75 (clobber (reg:CC CC_REGNUM))]
78 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
79 "TARGET_THUMB2 && reload_completed"
80 [(set (reg:CC CC_REGNUM)
81 (compare:CC (match_dup 1) (match_dup 2)))
82 (cond_exec (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
86 [(set_attr "conds" "clob")
87 (set_attr "length" "6,6,10")
88 (set_attr "enabled_for_short_it" "yes,yes,no")
89 (set_attr "type" "multiple")]
92 (define_insn_and_split "*thumb2_uminsi3"
93 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
94 (umin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
95 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
96 (clobber (reg:CC CC_REGNUM))]
99 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
100 "TARGET_THUMB2 && reload_completed"
101 [(set (reg:CC CC_REGNUM)
102 (compare:CC (match_dup 1) (match_dup 2)))
103 (cond_exec (geu:SI (reg:CC CC_REGNUM) (const_int 0))
107 [(set_attr "conds" "clob")
108 (set_attr "length" "6,6,10")
109 (set_attr "enabled_for_short_it" "yes,yes,no")
110 (set_attr "type" "multiple")]
113 (define_insn_and_split "*thumb2_abssi2"
114 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
115 (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0")))
116 (clobber (reg:CC CC_REGNUM))]
119 ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
120 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
121 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
122 "&& reload_completed"
125 if (REGNO(operands[0]) == REGNO(operands[1]))
127 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
129 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
131 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
135 (gen_rtx_SET (operands[0],
136 (gen_rtx_MINUS (SImode,
142 emit_insn (gen_rtx_SET (operands[0],
144 gen_rtx_ASHIFTRT (SImode,
148 emit_insn (gen_rtx_SET (operands[0],
149 gen_rtx_MINUS (SImode,
151 gen_rtx_ASHIFTRT (SImode,
157 [(set_attr "conds" "*,clob,clob")
158 (set_attr "shift" "1")
159 (set_attr "predicable" "yes,no,no")
160 (set_attr "enabled_for_short_it" "yes,yes,no")
161 (set_attr "ce_count" "2")
162 (set_attr "length" "8,6,10")
163 (set_attr "type" "multiple")]
166 (define_insn_and_split "*thumb2_neg_abssi2"
167 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
168 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0"))))
169 (clobber (reg:CC CC_REGNUM))]
172 ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
173 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
174 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
175 "&& reload_completed"
178 if (REGNO(operands[0]) == REGNO(operands[1]))
180 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
182 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
184 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
188 (gen_rtx_SET (operands[0],
189 (gen_rtx_MINUS (SImode,
195 emit_insn (gen_rtx_SET (operands[0],
197 gen_rtx_ASHIFTRT (SImode,
201 emit_insn (gen_rtx_SET (operands[0],
202 gen_rtx_MINUS (SImode,
203 gen_rtx_ASHIFTRT (SImode,
210 [(set_attr "conds" "*,clob,clob")
211 (set_attr "shift" "1")
212 (set_attr "predicable" "yes,no,no")
213 (set_attr "enabled_for_short_it" "yes,yes,no")
214 (set_attr "ce_count" "2")
215 (set_attr "length" "8,6,10")
216 (set_attr "type" "multiple")]
219 ;; Pop a single register as its size is preferred over a post-incremental load
220 (define_insn "*thumb2_pop_single"
221 [(set (match_operand:SI 0 "low_register_operand" "=r")
222 (mem:SI (post_inc:SI (reg:SI SP_REGNUM))))]
223 "TARGET_THUMB2 && (reload_in_progress || reload_completed)"
225 [(set_attr "type" "load_4")
226 (set_attr "length" "2")
227 (set_attr "predicable" "yes")]
230 ;; We have two alternatives here for memory loads (and similarly for stores)
231 ;; to reflect the fact that the permissible constant pool ranges differ
232 ;; between ldr instructions taking low regs and ldr instructions taking high
233 ;; regs. The high register alternatives are not taken into account when
234 ;; choosing register preferences in order to reflect their expense.
235 (define_insn "*thumb2_movsi_insn"
236 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,lk*r,m")
237 (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,lk*r"))]
238 "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
239 && ( register_operand (operands[0], SImode)
240 || register_operand (operands[1], SImode))"
242 switch (which_alternative)
247 return \"mov%?\\t%0, %1\";
248 case 3: return \"mvn%?\\t%0, #%B1\";
249 case 4: return \"movw%?\\t%0, %1\";
251 /* Cannot load it directly, split to load it via MOV / MOVT. */
252 if (!MEM_P (operands[1]) && arm_disable_literal_pool)
254 return \"ldr%?\\t%0, %1\";
255 case 6: return \"str%?\\t%1, %0\";
256 default: gcc_unreachable ();
259 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mvn_imm,mov_imm,load_4,store_4")
260 (set_attr "length" "2,4,2,4,4,4,4")
261 (set_attr "predicable" "yes")
262 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no")
263 (set_attr "pool_range" "*,*,*,*,*,1018,*")
264 (set_attr "neg_pool_range" "*,*,*,*,*,0,*")]
267 (define_insn "tls_load_dot_plus_four"
268 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
269 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
271 (match_operand 3 "" "")]
273 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
276 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
277 INTVAL (operands[3]));
278 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
280 [(set_attr "length" "4,4,6,6")
281 (set_attr "type" "multiple")]
284 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
285 ;; of the messiness associated with the ARM patterns.
286 (define_insn "*thumb2_movhi_insn"
287 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,l,r,m,r")
288 (match_operand:HI 1 "general_operand" "rk,I,Py,n,r,m"))]
290 && (register_operand (operands[0], HImode)
291 || register_operand (operands[1], HImode))"
293 mov%?\\t%0, %1\\t%@ movhi
294 mov%?\\t%0, %1\\t%@ movhi
295 mov%?\\t%0, %1\\t%@ movhi
296 movw%?\\t%0, %L1\\t%@ movhi
297 strh%?\\t%1, %0\\t%@ movhi
298 ldrh%?\\t%0, %1\\t%@ movhi"
299 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store_4,load_4")
300 (set_attr "predicable" "yes")
301 (set_attr "predicable_short_it" "yes,no,yes,no,no,no")
302 (set_attr "length" "2,4,2,4,4,4")
303 (set_attr "pool_range" "*,*,*,*,*,4094")
304 (set_attr "neg_pool_range" "*,*,*,*,*,250")]
307 (define_insn "*thumb2_storewb_pairsi"
308 [(set (match_operand:SI 0 "register_operand" "=&kr")
309 (plus:SI (match_operand:SI 1 "register_operand" "0")
310 (match_operand:SI 2 "const_int_operand" "n")))
311 (set (mem:SI (plus:SI (match_dup 0) (match_dup 2)))
312 (match_operand:SI 3 "register_operand" "r"))
313 (set (mem:SI (plus:SI (match_dup 0)
314 (match_operand:SI 5 "const_int_operand" "n")))
315 (match_operand:SI 4 "register_operand" "r"))]
317 && INTVAL (operands[5]) == INTVAL (operands[2]) + 4"
318 "strd\\t%3, %4, [%0, %2]!"
319 [(set_attr "type" "store_8")]
322 (define_insn_and_split "*thumb2_mov_scc"
323 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
324 (match_operator:SI 1 "arm_comparison_operator_mode"
325 [(match_operand 2 "cc_register" "") (const_int 0)]))]
327 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
330 (if_then_else:SI (match_dup 1)
334 [(set_attr "conds" "use")
335 (set_attr "enabled_for_short_it" "yes,no")
336 (set_attr "length" "8,10")
337 (set_attr "type" "multiple")]
340 (define_insn_and_split "*thumb2_mov_negscc"
341 [(set (match_operand:SI 0 "s_register_operand" "=r")
342 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
343 [(match_operand 2 "cc_register" "") (const_int 0)])))]
346 && !arm_borrow_operation (operands[1], SImode)"
347 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
350 (if_then_else:SI (match_dup 1)
354 operands[3] = GEN_INT (~0);
356 [(set_attr "conds" "use")
357 (set_attr "length" "10")
358 (set_attr "type" "multiple")]
361 (define_insn_and_split "*thumb2_mov_negscc_strict_it"
362 [(set (match_operand:SI 0 "low_register_operand" "=l")
363 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
364 [(match_operand 2 "cc_register" "") (const_int 0)])))]
367 && !arm_borrow_operation (operands[1], SImode)"
368 "#" ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\"
369 "&& reload_completed"
372 (cond_exec (match_dup 4)
376 operands[3] = GEN_INT (~0);
377 machine_mode mode = GET_MODE (operands[2]);
378 enum rtx_code rc = GET_CODE (operands[1]);
380 if (mode == CCFPmode || mode == CCFPEmode)
381 rc = reverse_condition_maybe_unordered (rc);
383 rc = reverse_condition (rc);
384 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
387 [(set_attr "conds" "use")
388 (set_attr "length" "8")
389 (set_attr "type" "multiple")]
392 (define_insn_and_split "*thumb2_mov_notscc"
393 [(set (match_operand:SI 0 "s_register_operand" "=r")
394 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
395 [(match_operand 2 "cc_register" "") (const_int 0)])))]
396 "TARGET_THUMB2 && !arm_restrict_it"
397 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
400 (if_then_else:SI (match_dup 1)
404 operands[3] = GEN_INT (~1);
405 operands[4] = GEN_INT (~0);
407 [(set_attr "conds" "use")
408 (set_attr "length" "10")
409 (set_attr "type" "multiple")]
412 (define_insn_and_split "*thumb2_mov_notscc_strict_it"
413 [(set (match_operand:SI 0 "low_register_operand" "=l")
414 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
415 [(match_operand 2 "cc_register" "") (const_int 0)])))]
416 "TARGET_THUMB2 && arm_restrict_it"
417 "#" ; "mvn %0, #0 ; it%d1 ; lsl%d1 %0, %0, #1"
418 "&& reload_completed"
421 (cond_exec (match_dup 4)
423 (ashift:SI (match_dup 0)
426 operands[3] = GEN_INT (~0);
427 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
428 VOIDmode, operands[2], const0_rtx);
430 [(set_attr "conds" "use")
431 (set_attr "length" "8")
432 (set_attr "type" "multiple")]
435 (define_insn_and_split "*thumb2_movsicc_insn"
436 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r")
438 (match_operator 3 "arm_comparison_operator"
439 [(match_operand 4 "cc_register" "") (const_int 0)])
440 (match_operand:SI 1 "arm_not_operand" "0 ,lPy,0 ,0,rI,K,I ,r,rI,K ,K,r")
441 (match_operand:SI 2 "arm_not_operand" "lPy,0 ,rI,K,0 ,0,rI,I,K ,rI,K,r")))]
444 it\\t%D3\;mov%D3\\t%0, %2
445 it\\t%d3\;mov%d3\\t%0, %1
446 it\\t%D3\;mov%D3\\t%0, %2
447 it\\t%D3\;mvn%D3\\t%0, #%B2
448 it\\t%d3\;mov%d3\\t%0, %1
449 it\\t%d3\;mvn%d3\\t%0, #%B1
456 ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
457 ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
458 ; alt 8: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
459 ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
460 ; alt 10: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
461 ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
462 "&& reload_completed"
465 enum rtx_code rev_code;
469 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
471 gen_rtx_SET (operands[0], operands[1])));
472 rev_code = GET_CODE (operands[3]);
473 mode = GET_MODE (operands[4]);
474 if (mode == CCFPmode || mode == CCFPEmode)
475 rev_code = reverse_condition_maybe_unordered (rev_code);
477 rev_code = reverse_condition (rev_code);
479 rev_cond = gen_rtx_fmt_ee (rev_code,
481 gen_rtx_REG (mode, CC_REGNUM),
483 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
485 gen_rtx_SET (operands[0], operands[2])));
488 [(set_attr "length" "4,4,6,6,6,6,10,8,10,10,10,6")
489 (set_attr "enabled_for_short_it" "yes,yes,no,no,no,no,no,no,no,no,no,yes")
490 (set_attr "conds" "use")
491 (set_attr_alternative "type"
492 [(if_then_else (match_operand 2 "const_int_operand" "")
493 (const_string "mov_imm")
494 (const_string "mov_reg"))
495 (if_then_else (match_operand 1 "const_int_operand" "")
496 (const_string "mov_imm")
497 (const_string "mov_reg"))
498 (if_then_else (match_operand 2 "const_int_operand" "")
499 (const_string "mov_imm")
500 (const_string "mov_reg"))
501 (const_string "mvn_imm")
502 (if_then_else (match_operand 1 "const_int_operand" "")
503 (const_string "mov_imm")
504 (const_string "mov_reg"))
505 (const_string "mvn_imm")
506 (const_string "multiple")
507 (const_string "multiple")
508 (const_string "multiple")
509 (const_string "multiple")
510 (const_string "multiple")
511 (const_string "multiple")])]
514 (define_insn "*thumb2_movsfcc_soft_insn"
515 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
516 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
517 [(match_operand 4 "cc_register" "") (const_int 0)])
518 (match_operand:SF 1 "s_register_operand" "0,r")
519 (match_operand:SF 2 "s_register_operand" "r,0")))]
520 "TARGET_THUMB2 && TARGET_SOFT_FLOAT && !TARGET_HAVE_MVE"
522 it\\t%D3\;mov%D3\\t%0, %2
523 it\\t%d3\;mov%d3\\t%0, %1"
524 [(set_attr "length" "6,6")
525 (set_attr "conds" "use")
526 (set_attr "type" "multiple")]
529 (define_insn "*call_reg_thumb2"
530 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
531 (match_operand 1 "" ""))
532 (use (match_operand 2 "" ""))
533 (clobber (reg:SI LR_REGNUM))]
536 [(set_attr "type" "call")]
539 (define_insn "*nonsecure_call_reg_thumb2"
540 [(call (unspec:SI [(mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))]
541 UNSPEC_NONSECURE_MEM)
542 (match_operand 1 "" ""))
543 (use (match_operand 2 "" ""))
544 (clobber (reg:SI LR_REGNUM))]
545 "TARGET_THUMB2 && use_cmse"
547 if (TARGET_HAVE_FPCXT_CMSE)
550 return "bl\\t__gnu_cmse_nonsecure_call";
552 [(set_attr "length" "4")
553 (set_attr "type" "call")]
556 (define_insn "*call_value_reg_thumb2"
557 [(set (match_operand 0 "" "")
558 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
559 (match_operand 2 "" "")))
560 (use (match_operand 3 "" ""))
561 (clobber (reg:SI LR_REGNUM))]
564 [(set_attr "type" "call")]
567 (define_insn "*nonsecure_call_value_reg_thumb2"
568 [(set (match_operand 0 "" "")
570 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
571 UNSPEC_NONSECURE_MEM)
572 (match_operand 2 "" "")))
573 (use (match_operand 3 "" ""))
574 (clobber (reg:SI LR_REGNUM))]
575 "TARGET_THUMB2 && use_cmse"
577 if (TARGET_HAVE_FPCXT_CMSE)
580 return "bl\\t__gnu_cmse_nonsecure_call";
582 [(set_attr "length" "4")
583 (set_attr "type" "call")]
586 (define_insn "*thumb2_indirect_jump"
588 (match_operand:SI 0 "register_operand" "l*r"))]
591 [(set_attr "conds" "clob")
592 (set_attr "type" "branch")]
594 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
595 ;; addresses will have the thumb bit set correctly.
598 (define_insn_and_split "*thumb2_and_scc"
599 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
600 (and:SI (match_operator:SI 1 "arm_comparison_operator"
601 [(match_operand 2 "cc_register" "") (const_int 0)])
602 (match_operand:SI 3 "s_register_operand" "r")))]
604 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
605 "&& reload_completed"
607 (and:SI (match_dup 3) (const_int 1)))
608 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
610 machine_mode mode = GET_MODE (operands[2]);
611 enum rtx_code rc = GET_CODE (operands[1]);
613 if (mode == CCFPmode || mode == CCFPEmode)
614 rc = reverse_condition_maybe_unordered (rc);
616 rc = reverse_condition (rc);
617 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
619 [(set_attr "conds" "use")
620 (set_attr "type" "multiple")
621 (set (attr "length") (if_then_else (match_test "arm_restrict_it")
626 (define_insn_and_split "*thumb2_ior_scc"
627 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
628 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
629 [(match_operand 2 "cc_register" "") (const_int 0)])
630 (match_operand:SI 3 "s_register_operand" "0,?r")))]
631 "TARGET_THUMB2 && !arm_restrict_it"
633 it\\t%d1\;orr%d1\\t%0, %3, #1
635 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
637 && REGNO (operands [0]) != REGNO (operands[3])"
638 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
639 (cond_exec (match_dup 4) (set (match_dup 0)
640 (ior:SI (match_dup 3) (const_int 1))))]
642 machine_mode mode = GET_MODE (operands[2]);
643 enum rtx_code rc = GET_CODE (operands[1]);
645 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
646 if (mode == CCFPmode || mode == CCFPEmode)
647 rc = reverse_condition_maybe_unordered (rc);
649 rc = reverse_condition (rc);
650 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
652 [(set_attr "conds" "use")
653 (set_attr "length" "6,10")
654 (set_attr "type" "multiple")]
657 (define_insn_and_split "*thumb2_ior_scc_strict_it"
658 [(set (match_operand:SI 0 "s_register_operand" "=&r")
659 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
660 [(match_operand 3 "cc_register" "") (const_int 0)])
661 (match_operand:SI 1 "s_register_operand" "r")))]
662 "TARGET_THUMB2 && arm_restrict_it"
663 "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
664 "&& reload_completed"
665 [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
666 (cond_exec (match_dup 4)
667 (set (match_dup 0) (match_dup 1)))]
669 machine_mode mode = GET_MODE (operands[3]);
670 rtx_code rc = GET_CODE (operands[2]);
672 if (mode == CCFPmode || mode == CCFPEmode)
673 rc = reverse_condition_maybe_unordered (rc);
675 rc = reverse_condition (rc);
676 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
678 [(set_attr "conds" "use")
679 (set_attr "length" "8")
680 (set_attr "type" "multiple")]
683 (define_insn "*thumb2_cond_move"
684 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
685 (if_then_else:SI (match_operator 3 "equality_operator"
686 [(match_operator 4 "arm_comparison_operator"
687 [(match_operand 5 "cc_register" "") (const_int 0)])
689 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
690 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
693 if (GET_CODE (operands[3]) == NE)
695 if (which_alternative != 1)
696 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
697 if (which_alternative != 0)
698 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
701 switch (which_alternative)
704 output_asm_insn (\"it\\t%d4\", operands);
707 output_asm_insn (\"it\\t%D4\", operands);
711 output_asm_insn (\"it\\t%D4\", operands);
713 output_asm_insn (\"ite\\t%D4\", operands);
718 if (which_alternative != 0)
720 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
721 if (arm_restrict_it && which_alternative == 2)
722 output_asm_insn (\"it\\t%d4\", operands);
724 if (which_alternative != 1)
725 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
728 [(set_attr "conds" "use")
729 (set_attr "length" "6,6,10")
730 (set_attr "type" "multiple")]
733 (define_insn "*thumb2_cond_arith"
734 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
735 (match_operator:SI 5 "shiftable_operator"
736 [(match_operator:SI 4 "arm_comparison_operator"
737 [(match_operand:SI 2 "s_register_operand" "r,r")
738 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
739 (match_operand:SI 1 "s_register_operand" "0,?r")]))
740 (clobber (reg:CC CC_REGNUM))]
741 "TARGET_THUMB2 && !arm_restrict_it"
743 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
744 return \"%i5\\t%0, %1, %2, lsr #31\";
746 output_asm_insn (\"cmp\\t%2, %3\", operands);
748 if (GET_CODE (operands[5]) == PLUS && TARGET_COND_ARITH)
749 return \"cinc\\t%0, %1, %d4\";
751 if (GET_CODE (operands[5]) == AND)
753 output_asm_insn (\"ite\\t%D4\", operands);
754 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
756 else if (GET_CODE (operands[5]) == MINUS)
758 output_asm_insn (\"ite\\t%D4\", operands);
759 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
761 else if (which_alternative != 0)
763 output_asm_insn (\"ite\\t%D4\", operands);
764 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
767 output_asm_insn (\"it\\t%d4\", operands);
768 return \"%i5%d4\\t%0, %1, #1\";
770 [(set_attr "conds" "clob")
771 (set_attr "length" "14")
772 (set_attr "type" "multiple")]
775 (define_insn_and_split "*thumb2_cond_arith_strict_it"
776 [(set (match_operand:SI 0 "s_register_operand" "=l")
777 (match_operator:SI 5 "shiftable_operator_strict_it"
778 [(match_operator:SI 4 "arm_comparison_operator"
779 [(match_operand:SI 2 "s_register_operand" "r")
780 (match_operand:SI 3 "arm_rhs_operand" "rI")])
781 (match_operand:SI 1 "s_register_operand" "0")]))
782 (clobber (reg:CC CC_REGNUM))]
783 "TARGET_THUMB2 && arm_restrict_it"
785 "&& reload_completed"
788 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
790 /* %i5 %0, %1, %2, lsr #31 */
791 rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
794 switch (GET_CODE (operands[5]))
797 op = gen_rtx_AND (SImode, shifted_op, operands[1]);
800 op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
802 default: gcc_unreachable ();
804 emit_insn (gen_rtx_SET (operands[0], op));
809 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
810 gen_rtx_COMPARE (CCmode, operands[2],
813 if (GET_CODE (operands[5]) == AND)
818 enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
819 emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
821 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
822 gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
823 gen_rtx_SET (operands[0], const0_rtx)));
829 %i5%d4\\t%0, %1, #1 */
830 emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
832 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
833 gen_rtx_SET (operands[0],
834 gen_rtx_PLUS (SImode,
841 [(set_attr "conds" "clob")
842 (set_attr "length" "12")
843 (set_attr "type" "multiple")]
846 (define_insn "*thumb2_cond_sub"
847 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
848 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
849 (match_operator:SI 4 "arm_comparison_operator"
850 [(match_operand:SI 2 "s_register_operand" "r,r")
851 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
852 (clobber (reg:CC CC_REGNUM))]
855 output_asm_insn (\"cmp\\t%2, %3\", operands);
856 if (which_alternative != 0)
860 output_asm_insn (\"mov\\t%0, %1\", operands);
861 output_asm_insn (\"it\\t%d4\", operands);
865 output_asm_insn (\"ite\\t%D4\", operands);
866 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
870 output_asm_insn (\"it\\t%d4\", operands);
871 return \"sub%d4\\t%0, %1, #1\";
873 [(set_attr "conds" "clob")
874 (set_attr "length" "10,14")
875 (set_attr "type" "multiple")]
878 (define_insn_and_split "*thumb2_negscc"
879 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
880 (neg:SI (match_operator 3 "arm_comparison_operator"
881 [(match_operand:SI 1 "s_register_operand" "r")
882 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
883 (clobber (reg:CC CC_REGNUM))]
884 "TARGET_THUMB2 && !TARGET_COND_ARITH"
886 "&& reload_completed"
889 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
891 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
893 /* Emit asr\\t%0, %1, #31 */
894 emit_insn (gen_rtx_SET (operands[0],
895 gen_rtx_ASHIFTRT (SImode,
900 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
902 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
903 if (CONST_INT_P (operands[2]))
904 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
905 gen_int_mode (-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_csinv"
946 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
948 (match_operand 1 "arm_comparison_operation" "")
949 (not:SI (match_operand:SI 2 "arm_general_register_operand" "r, r"))
950 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
953 csinv\\t%0, %3, %2, %D1
954 csinv\\t%0, zr, %2, %D1"
955 [(set_attr "type" "csel")
956 (set_attr "predicable" "no")]
959 (define_insn "*thumb2_csinc"
960 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
962 (match_operand 1 "arm_comparison_operation" "")
963 (plus:SI (match_operand:SI 2 "arm_general_register_operand" "r, r")
965 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
968 csinc\\t%0, %3, %2, %D1
969 csinc\\t%0, zr, %2, %D1"
970 [(set_attr "type" "csel")
971 (set_attr "predicable" "no")]
974 (define_insn "*thumb2_csneg"
975 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
977 (match_operand 1 "arm_comparison_operation" "")
978 (neg:SI (match_operand:SI 2 "arm_general_register_operand" "r, r"))
979 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
982 csneg\\t%0, %3, %2, %D1
983 csneg\\t%0, zr, %2, %D1"
984 [(set_attr "type" "csel")
985 (set_attr "predicable" "no")]
988 (define_insn "*thumb2_movcond"
989 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
991 (match_operator 5 "arm_comparison_operator"
992 [(match_operand:SI 3 "s_register_operand" "r,r,r")
993 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
994 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
995 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
996 (clobber (reg:CC CC_REGNUM))]
997 "TARGET_THUMB2 && !TARGET_COND_ARITH"
999 if (GET_CODE (operands[5]) == LT
1000 && (operands[4] == const0_rtx))
1002 if (which_alternative != 1 && REG_P (operands[1]))
1004 if (operands[2] == const0_rtx)
1005 return \"and\\t%0, %1, %3, asr #31\";
1006 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
1008 else if (which_alternative != 0 && REG_P (operands[2]))
1010 if (operands[1] == const0_rtx)
1011 return \"bic\\t%0, %2, %3, asr #31\";
1012 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
1014 /* The only case that falls through to here is when both ops 1 & 2
1018 if (GET_CODE (operands[5]) == GE
1019 && (operands[4] == const0_rtx))
1021 if (which_alternative != 1 && REG_P (operands[1]))
1023 if (operands[2] == const0_rtx)
1024 return \"bic\\t%0, %1, %3, asr #31\";
1025 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
1027 else if (which_alternative != 0 && REG_P (operands[2]))
1029 if (operands[1] == const0_rtx)
1030 return \"and\\t%0, %2, %3, asr #31\";
1031 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
1033 /* The only case that falls through to here is when both ops 1 & 2
1036 if (CONST_INT_P (operands[4])
1037 && !const_ok_for_arm (INTVAL (operands[4])))
1038 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
1040 output_asm_insn (\"cmp\\t%3, %4\", operands);
1041 switch (which_alternative)
1044 output_asm_insn (\"it\\t%D5\", operands);
1047 output_asm_insn (\"it\\t%d5\", operands);
1050 if (arm_restrict_it)
1052 output_asm_insn (\"mov\\t%0, %1\", operands);
1053 output_asm_insn (\"it\\t%D5\", operands);
1056 output_asm_insn (\"ite\\t%d5\", operands);
1061 if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1062 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1063 if (which_alternative != 1)
1064 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1067 [(set_attr "conds" "clob")
1068 (set_attr "length" "10,10,14")
1069 (set_attr "type" "multiple")]
1072 ;; Zero and sign extension instructions.
1074 ;; All supported Thumb2 implementations are armv6, so only that case is
1076 (define_insn "*thumb2_extendqisi_v6"
1077 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1078 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1079 "TARGET_THUMB2 && arm_arch6"
1083 [(set_attr "type" "extend,load_byte")
1084 (set_attr "predicable" "yes")
1085 (set_attr "pool_range" "*,4094")
1086 (set_attr "neg_pool_range" "*,250")]
1089 (define_insn "*thumb2_zero_extendhisi2_v6"
1090 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1091 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1092 "TARGET_THUMB2 && arm_arch6"
1096 [(set_attr "type" "extend,load_byte")
1097 (set_attr "predicable" "yes")
1098 (set_attr "pool_range" "*,4094")
1099 (set_attr "neg_pool_range" "*,250")]
1102 (define_insn "thumb2_zero_extendqisi2_v6"
1103 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1104 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1105 "TARGET_THUMB2 && arm_arch6"
1108 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1109 [(set_attr "type" "extend,load_byte")
1110 (set_attr "predicable" "yes")
1111 (set_attr "pool_range" "*,4094")
1112 (set_attr "neg_pool_range" "*,250")]
1115 (define_expand "thumb2_casesi_internal"
1116 [(parallel [(set (pc)
1118 (leu (match_operand:SI 0 "s_register_operand")
1119 (match_operand:SI 1 "arm_rhs_operand"))
1121 (label_ref:SI (match_operand 3 ""))))
1122 (clobber (reg:CC CC_REGNUM))
1123 (clobber (match_scratch:SI 5))
1124 (use (label_ref:SI (match_operand 2 "")))])]
1125 "TARGET_THUMB2 && !flag_pic"
1127 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1128 operands[4] = gen_rtx_PLUS (SImode, operands[4],
1129 gen_rtx_LABEL_REF (SImode, operands[2]));
1130 operands[4] = gen_rtx_MEM (SImode, operands[4]);
1131 MEM_READONLY_P (operands[4]) = 1;
1132 MEM_NOTRAP_P (operands[4]) = 1;
1135 (define_insn "*thumb2_casesi_internal"
1136 [(parallel [(set (pc)
1138 (leu (match_operand:SI 0 "s_register_operand" "r")
1139 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1140 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1141 (label_ref:SI (match_operand 2 "" ""))))
1142 (label_ref:SI (match_operand 3 "" ""))))
1143 (clobber (reg:CC CC_REGNUM))
1144 (clobber (match_scratch:SI 4 "=&r"))
1145 (use (label_ref:SI (match_dup 2)))])]
1146 "TARGET_THUMB2 && !flag_pic"
1147 "* return thumb2_output_casesi(operands);"
1148 [(set_attr "conds" "clob")
1149 (set_attr "length" "16")
1150 (set_attr "type" "multiple")]
1153 (define_expand "thumb2_casesi_internal_pic"
1154 [(parallel [(set (pc)
1156 (leu (match_operand:SI 0 "s_register_operand")
1157 (match_operand:SI 1 "arm_rhs_operand"))
1159 (label_ref:SI (match_operand 3 ""))))
1160 (clobber (reg:CC CC_REGNUM))
1161 (clobber (match_scratch:SI 5))
1162 (clobber (match_scratch:SI 6))
1163 (use (label_ref:SI (match_operand 2 "")))])]
1164 "TARGET_THUMB2 && flag_pic"
1166 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1167 operands[4] = gen_rtx_PLUS (SImode, operands[4],
1168 gen_rtx_LABEL_REF (SImode, operands[2]));
1169 operands[4] = gen_rtx_MEM (SImode, operands[4]);
1170 MEM_READONLY_P (operands[4]) = 1;
1171 MEM_NOTRAP_P (operands[4]) = 1;
1174 (define_insn "*thumb2_casesi_internal_pic"
1175 [(parallel [(set (pc)
1177 (leu (match_operand:SI 0 "s_register_operand" "r")
1178 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1179 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1180 (label_ref:SI (match_operand 2 "" ""))))
1181 (label_ref:SI (match_operand 3 "" ""))))
1182 (clobber (reg:CC CC_REGNUM))
1183 (clobber (match_scratch:SI 4 "=&r"))
1184 (clobber (match_scratch:SI 5 "=r"))
1185 (use (label_ref:SI (match_dup 2)))])]
1186 "TARGET_THUMB2 && flag_pic"
1187 "* return thumb2_output_casesi(operands);"
1188 [(set_attr "conds" "clob")
1189 (set_attr "length" "20")
1190 (set_attr "type" "multiple")]
1193 (define_insn "*thumb2_return"
1195 "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1196 "* return output_return_instruction (const_true_rtx, true, false, true);"
1197 [(set_attr "type" "branch")
1198 (set_attr "length" "4")]
1201 (define_insn "*thumb2_cmse_entry_return"
1203 "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1204 "* return output_return_instruction (const_true_rtx, true, false, true);"
1205 [(set_attr "type" "branch")
1206 ; This is a return from a cmse_nonsecure_entry function so code will be
1207 ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1208 ; we adapt the length accordingly.
1209 (set (attr "length")
1210 (if_then_else (match_test "TARGET_HARD_FLOAT")
1213 ; We do not support predicate execution of returns from cmse_nonsecure_entry
1214 ; functions because we need to clear the APSR. Since predicable has to be
1215 ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1217 (set_attr "predicable" "no")]
1220 (define_insn_and_split "thumb2_eh_return"
1221 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1223 (clobber (match_scratch:SI 1 "=&r"))]
1226 "&& reload_completed"
1230 thumb_set_return_address (operands[0], operands[1]);
1235 (define_insn "*thumb2_alusi3_short"
1236 [(set (match_operand:SI 0 "s_register_operand" "=l")
1237 (match_operator:SI 3 "thumb_16bit_operator"
1238 [(match_operand:SI 1 "s_register_operand" "0")
1239 (match_operand:SI 2 "s_register_operand" "l")]))
1240 (clobber (reg:CC CC_REGNUM))]
1241 "TARGET_THUMB2 && reload_completed
1242 && GET_CODE(operands[3]) != PLUS
1243 && GET_CODE(operands[3]) != MINUS"
1244 "%I3%!\\t%0, %1, %2"
1245 [(set_attr "predicable" "yes")
1246 (set_attr "length" "2")
1247 (set_attr "type" "alu_sreg")]
1250 (define_insn "*thumb2_shiftsi3_short"
1251 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1252 (match_operator:SI 3 "shift_operator"
1253 [(match_operand:SI 1 "low_register_operand" "0,l")
1254 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1255 (clobber (reg:CC CC_REGNUM))]
1256 "TARGET_THUMB2 && reload_completed
1257 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1258 || REG_P (operands[2]))"
1259 "* return arm_output_shift(operands, 2);"
1260 [(set_attr "predicable" "yes")
1261 (set_attr "shift" "1")
1262 (set_attr "length" "2")
1263 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1264 (if_then_else (match_operand 3 "alu_shift_operator_lsl_1_to_4")
1265 (const_string "alu_shift_imm_lsl_1to4")
1266 (const_string "alu_shift_imm_other"))
1267 (const_string "alu_shift_reg")))]
1270 (define_insn "*thumb2_mov<mode>_shortim"
1271 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1272 (match_operand:QHSI 1 "const_int_operand" "I"))
1273 (clobber (reg:CC CC_REGNUM))]
1274 "TARGET_THUMB2 && reload_completed"
1276 [(set_attr "predicable" "yes")
1277 (set_attr "length" "2")
1278 (set_attr "type" "mov_imm")]
1281 (define_insn "*thumb2_addsi_short"
1282 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1283 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1284 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1285 (clobber (reg:CC CC_REGNUM))]
1286 "TARGET_THUMB2 && reload_completed"
1290 if (CONST_INT_P (operands[2]))
1291 val = INTVAL(operands[2]);
1295 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
1296 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1297 return \"sub%!\\t%0, %1, #%n2\";
1299 return \"add%!\\t%0, %1, %2\";
1301 [(set_attr "predicable" "yes")
1302 (set_attr "length" "2")
1303 (set_attr_alternative "type"
1304 [(if_then_else (match_operand 2 "const_int_operand" "")
1305 (const_string "alu_imm")
1306 (const_string "alu_sreg"))
1307 (const_string "alu_imm")])]
1310 (define_insn "*thumb2_subsi_short"
1311 [(set (match_operand:SI 0 "low_register_operand" "=l")
1312 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1313 (match_operand:SI 2 "low_register_operand" "l")))
1314 (clobber (reg:CC CC_REGNUM))]
1315 "TARGET_THUMB2 && reload_completed"
1316 "sub%!\\t%0, %1, %2"
1317 [(set_attr "predicable" "yes")
1318 (set_attr "length" "2")
1319 (set_attr "type" "alu_sreg")]
1323 [(set (match_operand:CC 0 "cc_register" "")
1324 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1325 (match_operand:SI 2 "const_int_operand" "")))]
1327 && peep2_reg_dead_p (1, operands[1])
1328 && satisfies_constraint_Pw (operands[2])"
1330 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1331 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1332 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1336 [(match_scratch:SI 3 "l")
1337 (set (match_operand:CC 0 "cc_register" "")
1338 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1339 (match_operand:SI 2 "const_int_operand" "")))]
1341 && satisfies_constraint_Px (operands[2])"
1343 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1344 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1345 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1348 (define_insn "thumb2_addsi3_compare0"
1349 [(set (reg:CC_NZ CC_REGNUM)
1351 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1352 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1354 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1355 (plus:SI (match_dup 1) (match_dup 2)))]
1360 if (CONST_INT_P (operands[2]))
1361 val = INTVAL (operands[2]);
1365 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1366 return \"subs\\t%0, %1, #%n2\";
1368 return \"adds\\t%0, %1, %2\";
1370 [(set_attr "conds" "set")
1371 (set_attr "length" "2,2,4")
1372 (set_attr_alternative "type"
1373 [(if_then_else (match_operand 2 "const_int_operand" "")
1374 (const_string "alus_imm")
1375 (const_string "alus_sreg"))
1376 (const_string "alus_imm")
1377 (if_then_else (match_operand 2 "const_int_operand" "")
1378 (const_string "alus_imm")
1379 (const_string "alus_sreg"))])]
1382 (define_insn "*thumb2_addsi3_compare0_scratch"
1383 [(set (reg:CC_NZ CC_REGNUM)
1385 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r")
1386 (match_operand:SI 1 "arm_add_operand" "lPv,rIL"))
1392 if (CONST_INT_P (operands[1]))
1393 val = INTVAL (operands[1]);
1397 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1398 return \"cmp\\t%0, #%n1\";
1400 return \"cmn\\t%0, %1\";
1402 [(set_attr "conds" "set")
1403 (set_attr "length" "2,4")
1404 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1405 (const_string "alus_imm")
1406 (const_string "alus_sreg")))]
1409 (define_insn "*thumb2_mulsi_short"
1410 [(set (match_operand:SI 0 "low_register_operand" "=l")
1411 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1412 (match_operand:SI 2 "low_register_operand" "l")))
1413 (clobber (reg:CC CC_REGNUM))]
1414 "TARGET_THUMB2 && optimize_size && reload_completed"
1415 "mul%!\\t%0, %2, %0"
1416 [(set_attr "predicable" "yes")
1417 (set_attr "length" "2")
1418 (set_attr "type" "muls")])
1420 (define_insn "*thumb2_mulsi_short_compare0"
1421 [(set (reg:CC_NZ CC_REGNUM)
1423 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1424 (match_operand:SI 2 "register_operand" "l"))
1426 (set (match_operand:SI 0 "register_operand" "=l")
1427 (mult:SI (match_dup 1) (match_dup 2)))]
1428 "TARGET_THUMB2 && optimize_size"
1430 [(set_attr "length" "2")
1431 (set_attr "type" "muls")])
1433 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1434 [(set (reg:CC_NZ CC_REGNUM)
1436 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1437 (match_operand:SI 2 "register_operand" "l"))
1439 (clobber (match_scratch:SI 0 "=l"))]
1440 "TARGET_THUMB2 && optimize_size"
1442 [(set_attr "length" "2")
1443 (set_attr "type" "muls")])
1445 (define_insn "*thumb2_cbz"
1446 [(set (pc) (if_then_else
1447 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1449 (label_ref (match_operand 1 "" ""))
1451 (clobber (reg:CC CC_REGNUM))]
1454 if (get_attr_length (insn) == 2)
1455 return \"cbz\\t%0, %l1\";
1457 return \"cmp\\t%0, #0\;beq\\t%l1\";
1459 [(set (attr "length")
1461 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1462 (le (minus (match_dup 1) (pc)) (const_int 128))
1463 (not (match_test "which_alternative")))
1466 (set_attr "type" "branch,multiple")]
1469 (define_insn "*thumb2_cbnz"
1470 [(set (pc) (if_then_else
1471 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1473 (label_ref (match_operand 1 "" ""))
1475 (clobber (reg:CC CC_REGNUM))]
1478 if (get_attr_length (insn) == 2)
1479 return \"cbnz\\t%0, %l1\";
1481 return \"cmp\\t%0, #0\;bne\\t%l1\";
1483 [(set (attr "length")
1485 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1486 (le (minus (match_dup 1) (pc)) (const_int 128))
1487 (not (match_test "which_alternative")))
1490 (set_attr "type" "branch,multiple")]
1493 (define_insn "*thumb2_one_cmplsi2_short"
1494 [(set (match_operand:SI 0 "low_register_operand" "=l")
1495 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1496 (clobber (reg:CC CC_REGNUM))]
1497 "TARGET_THUMB2 && reload_completed"
1499 [(set_attr "predicable" "yes")
1500 (set_attr "length" "2")
1501 (set_attr "type" "mvn_reg")]
1504 (define_insn "*thumb2_negsi2_short"
1505 [(set (match_operand:SI 0 "low_register_operand" "=l")
1506 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1507 (clobber (reg:CC CC_REGNUM))]
1508 "TARGET_THUMB2 && reload_completed"
1510 [(set_attr "predicable" "yes")
1511 (set_attr "length" "2")
1512 (set_attr "type" "alu_sreg")]
1515 (define_insn "*orsi_notsi_si"
1516 [(set (match_operand:SI 0 "s_register_operand" "=r")
1517 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1518 (match_operand:SI 1 "s_register_operand" "r")))]
1520 "orn%?\\t%0, %1, %2"
1521 [(set_attr "predicable" "yes")
1522 (set_attr "type" "logic_reg")]
1525 (define_insn "*orsi_not_shiftsi_si"
1526 [(set (match_operand:SI 0 "s_register_operand" "=r")
1527 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1528 [(match_operand:SI 2 "s_register_operand" "r")
1529 (match_operand:SI 3 "const_int_operand" "M")]))
1530 (match_operand:SI 1 "s_register_operand" "r")))]
1532 "orn%?\\t%0, %1, %2%S4"
1533 [(set_attr "predicable" "yes")
1534 (set_attr "shift" "2")
1535 (set_attr "autodetect_type" "alu_shift_operator4")]
1539 [(set (match_operand:CC_NZ 0 "cc_register" "")
1540 (compare:CC_NZ (zero_extract:SI
1541 (match_operand:SI 1 "low_register_operand" "")
1543 (match_operand:SI 2 "const_int_operand" ""))
1545 (match_scratch:SI 3 "l")
1547 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1548 [(match_dup 0) (const_int 0)])
1549 (match_operand 5 "" "")
1550 (match_operand 6 "" "")))]
1552 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1553 && peep2_reg_dead_p (2, operands[0])"
1554 [(parallel [(set (match_dup 0)
1555 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1557 (clobber (match_dup 3))])
1559 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1560 (match_dup 5) (match_dup 6)))]
1562 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1563 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1564 VOIDmode, operands[0], const0_rtx);
1568 [(set (match_operand:CC_NZ 0 "cc_register" "")
1569 (compare:CC_NZ (zero_extract:SI
1570 (match_operand:SI 1 "low_register_operand" "")
1571 (match_operand:SI 2 "const_int_operand" "")
1574 (match_scratch:SI 3 "l")
1576 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1577 [(match_dup 0) (const_int 0)])
1578 (match_operand 5 "" "")
1579 (match_operand 6 "" "")))]
1581 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1582 && peep2_reg_dead_p (2, operands[0])"
1583 [(parallel [(set (match_dup 0)
1584 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1586 (clobber (match_dup 3))])
1588 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1589 (match_dup 5) (match_dup 6)))]
1591 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1594 ;; Define the subtract-one-and-jump insns so loop.c
1595 ;; knows what to generate.
1596 (define_expand "doloop_end"
1597 [(use (match_operand 0 "" "")) ; loop pseudo
1598 (use (match_operand 1 "" ""))] ; label
1602 /* Currently SMS relies on the do-loop pattern to recognize loops
1603 where (1) the control part consists of all insns defining and/or
1604 using a certain 'count' register and (2) the loop count can be
1605 adjusted by modifying this register prior to the loop.
1606 ??? The possible introduction of a new block to initialize the
1607 new IV can potentially affect branch optimizations.
1609 Also used to implement the low over head loops feature, which is part of
1610 the Armv8.1-M Mainline Low Overhead Branch (LOB) extension. */
1611 if (optimize > 0 && (flag_modulo_sched || TARGET_HAVE_LOB))
1620 if (GET_MODE (operands[0]) != SImode)
1625 /* Low over head loop instructions require the first operand to be LR. */
1626 if (TARGET_HAVE_LOB && arm_target_insn_ok_for_lob (operands [1]))
1627 s0 = gen_rtx_REG (SImode, LR_REGNUM);
1630 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1632 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1634 cmp = XVECEXP (PATTERN (insn), 0, 0);
1635 cc_reg = SET_DEST (cmp);
1636 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1637 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1638 emit_jump_insn (gen_rtx_SET (pc_rtx,
1639 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1647 (define_insn "*clear_apsr"
1648 [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1649 (clobber (reg:CC CC_REGNUM))]
1650 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1652 [(set_attr "predicable" "yes")]
1655 ;; The operands are validated through the clear_multiple_operation
1656 ;; match_parallel predicate rather than through constraints so enable it only
1658 (define_insn "*clear_multiple"
1659 [(match_parallel 0 "clear_multiple_operation"
1660 [(set (match_operand:SI 1 "register_operand" "")
1662 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1665 int i, num_saves = XVECLEN (operands[0], 0);
1667 strcpy (pattern, \"clrm%?\\t{\");
1668 for (i = 0; i < num_saves; i++)
1670 if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1672 strcat (pattern, \"APSR\");
1677 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1678 if (i < num_saves - 1)
1679 strcat (pattern, \", %|\");
1681 strcat (pattern, \"}\");
1682 output_asm_insn (pattern, operands);
1685 [(set_attr "predicable" "yes")]
1688 (define_insn "thumb2_asrl"
1689 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1690 (ashiftrt:DI (match_dup 0)
1691 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1693 "asrl%?\\t%Q0, %R0, %1"
1694 [(set_attr "predicable" "yes")])
1696 (define_insn "thumb2_lsll"
1697 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1698 (ashift:DI (match_dup 0)
1699 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1701 "lsll%?\\t%Q0, %R0, %1"
1702 [(set_attr "predicable" "yes")])
1704 (define_insn "thumb2_lsrl"
1705 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1706 (lshiftrt:DI (match_dup 0)
1707 (match_operand:SI 1 "long_shift_imm" "Pg")))]
1709 "lsrl%?\\t%Q0, %R0, %1"
1710 [(set_attr "predicable" "yes")])
1712 ;; Originally expanded by 'doloop_end'.
1713 (define_insn "*doloop_end_internal"
1716 (ne (reg:SI LR_REGNUM) (const_int 1))
1717 (label_ref (match_operand 0 "" ""))
1719 (set (reg:SI LR_REGNUM)
1720 (plus:SI (reg:SI LR_REGNUM) (const_int -1)))
1721 (clobber (reg:CC CC_REGNUM))]
1722 "TARGET_32BIT && TARGET_HAVE_LOB"
1724 if (get_attr_length (insn) == 4)
1725 return "le\t%|lr, %l0";
1727 return "subs\t%|lr, #1;bne\t%l0";
1729 [(set (attr "length")
1731 (ltu (minus (pc) (match_dup 0)) (const_int 1024))
1734 (set_attr "type" "branch")])
1736 (define_expand "doloop_begin"
1737 [(match_operand 0 "" "")
1738 (match_operand 1 "" "")]
1739 "TARGET_32BIT && TARGET_HAVE_LOB"
1741 if (REGNO (operands[0]) == LR_REGNUM)
1743 emit_insn (gen_dls_insn (operands[0]));
1750 (define_insn "dls_insn"
1751 [(set (reg:SI LR_REGNUM)
1752 (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))]
1753 "TARGET_32BIT && TARGET_HAVE_LOB"