1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2020 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 (const_string "alu_shift_imm")
1265 (const_string "alu_shift_reg")))]
1268 (define_insn "*thumb2_mov<mode>_shortim"
1269 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1270 (match_operand:QHSI 1 "const_int_operand" "I"))
1271 (clobber (reg:CC CC_REGNUM))]
1272 "TARGET_THUMB2 && reload_completed"
1274 [(set_attr "predicable" "yes")
1275 (set_attr "length" "2")
1276 (set_attr "type" "mov_imm")]
1279 (define_insn "*thumb2_addsi_short"
1280 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1281 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1282 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1283 (clobber (reg:CC CC_REGNUM))]
1284 "TARGET_THUMB2 && reload_completed"
1288 if (CONST_INT_P (operands[2]))
1289 val = INTVAL(operands[2]);
1293 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
1294 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1295 return \"sub%!\\t%0, %1, #%n2\";
1297 return \"add%!\\t%0, %1, %2\";
1299 [(set_attr "predicable" "yes")
1300 (set_attr "length" "2")
1301 (set_attr_alternative "type"
1302 [(if_then_else (match_operand 2 "const_int_operand" "")
1303 (const_string "alu_imm")
1304 (const_string "alu_sreg"))
1305 (const_string "alu_imm")])]
1308 (define_insn "*thumb2_subsi_short"
1309 [(set (match_operand:SI 0 "low_register_operand" "=l")
1310 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1311 (match_operand:SI 2 "low_register_operand" "l")))
1312 (clobber (reg:CC CC_REGNUM))]
1313 "TARGET_THUMB2 && reload_completed"
1314 "sub%!\\t%0, %1, %2"
1315 [(set_attr "predicable" "yes")
1316 (set_attr "length" "2")
1317 (set_attr "type" "alu_sreg")]
1321 [(set (match_operand:CC 0 "cc_register" "")
1322 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1323 (match_operand:SI 2 "const_int_operand" "")))]
1325 && peep2_reg_dead_p (1, operands[1])
1326 && satisfies_constraint_Pw (operands[2])"
1328 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1329 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1330 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1334 [(match_scratch:SI 3 "l")
1335 (set (match_operand:CC 0 "cc_register" "")
1336 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1337 (match_operand:SI 2 "const_int_operand" "")))]
1339 && satisfies_constraint_Px (operands[2])"
1341 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1342 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1343 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1346 (define_insn "thumb2_addsi3_compare0"
1347 [(set (reg:CC_NZ CC_REGNUM)
1349 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1350 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1352 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1353 (plus:SI (match_dup 1) (match_dup 2)))]
1358 if (CONST_INT_P (operands[2]))
1359 val = INTVAL (operands[2]);
1363 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1364 return \"subs\\t%0, %1, #%n2\";
1366 return \"adds\\t%0, %1, %2\";
1368 [(set_attr "conds" "set")
1369 (set_attr "length" "2,2,4")
1370 (set_attr_alternative "type"
1371 [(if_then_else (match_operand 2 "const_int_operand" "")
1372 (const_string "alus_imm")
1373 (const_string "alus_sreg"))
1374 (const_string "alus_imm")
1375 (if_then_else (match_operand 2 "const_int_operand" "")
1376 (const_string "alus_imm")
1377 (const_string "alus_sreg"))])]
1380 (define_insn "*thumb2_addsi3_compare0_scratch"
1381 [(set (reg:CC_NZ CC_REGNUM)
1383 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r")
1384 (match_operand:SI 1 "arm_add_operand" "lPv,rIL"))
1390 if (CONST_INT_P (operands[1]))
1391 val = INTVAL (operands[1]);
1395 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1396 return \"cmp\\t%0, #%n1\";
1398 return \"cmn\\t%0, %1\";
1400 [(set_attr "conds" "set")
1401 (set_attr "length" "2,4")
1402 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1403 (const_string "alus_imm")
1404 (const_string "alus_sreg")))]
1407 (define_insn "*thumb2_mulsi_short"
1408 [(set (match_operand:SI 0 "low_register_operand" "=l")
1409 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1410 (match_operand:SI 2 "low_register_operand" "l")))
1411 (clobber (reg:CC CC_REGNUM))]
1412 "TARGET_THUMB2 && optimize_size && reload_completed"
1413 "mul%!\\t%0, %2, %0"
1414 [(set_attr "predicable" "yes")
1415 (set_attr "length" "2")
1416 (set_attr "type" "muls")])
1418 (define_insn "*thumb2_mulsi_short_compare0"
1419 [(set (reg:CC_NZ CC_REGNUM)
1421 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1422 (match_operand:SI 2 "register_operand" "l"))
1424 (set (match_operand:SI 0 "register_operand" "=l")
1425 (mult:SI (match_dup 1) (match_dup 2)))]
1426 "TARGET_THUMB2 && optimize_size"
1428 [(set_attr "length" "2")
1429 (set_attr "type" "muls")])
1431 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1432 [(set (reg:CC_NZ CC_REGNUM)
1434 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1435 (match_operand:SI 2 "register_operand" "l"))
1437 (clobber (match_scratch:SI 0 "=l"))]
1438 "TARGET_THUMB2 && optimize_size"
1440 [(set_attr "length" "2")
1441 (set_attr "type" "muls")])
1443 (define_insn "*thumb2_cbz"
1444 [(set (pc) (if_then_else
1445 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1447 (label_ref (match_operand 1 "" ""))
1449 (clobber (reg:CC CC_REGNUM))]
1452 if (get_attr_length (insn) == 2)
1453 return \"cbz\\t%0, %l1\";
1455 return \"cmp\\t%0, #0\;beq\\t%l1\";
1457 [(set (attr "length")
1459 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1460 (le (minus (match_dup 1) (pc)) (const_int 128))
1461 (not (match_test "which_alternative")))
1464 (set_attr "type" "branch,multiple")]
1467 (define_insn "*thumb2_cbnz"
1468 [(set (pc) (if_then_else
1469 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1471 (label_ref (match_operand 1 "" ""))
1473 (clobber (reg:CC CC_REGNUM))]
1476 if (get_attr_length (insn) == 2)
1477 return \"cbnz\\t%0, %l1\";
1479 return \"cmp\\t%0, #0\;bne\\t%l1\";
1481 [(set (attr "length")
1483 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1484 (le (minus (match_dup 1) (pc)) (const_int 128))
1485 (not (match_test "which_alternative")))
1488 (set_attr "type" "branch,multiple")]
1491 (define_insn "*thumb2_one_cmplsi2_short"
1492 [(set (match_operand:SI 0 "low_register_operand" "=l")
1493 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1494 (clobber (reg:CC CC_REGNUM))]
1495 "TARGET_THUMB2 && reload_completed"
1497 [(set_attr "predicable" "yes")
1498 (set_attr "length" "2")
1499 (set_attr "type" "mvn_reg")]
1502 (define_insn "*thumb2_negsi2_short"
1503 [(set (match_operand:SI 0 "low_register_operand" "=l")
1504 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1505 (clobber (reg:CC CC_REGNUM))]
1506 "TARGET_THUMB2 && reload_completed"
1508 [(set_attr "predicable" "yes")
1509 (set_attr "length" "2")
1510 (set_attr "type" "alu_sreg")]
1513 (define_insn "*orsi_notsi_si"
1514 [(set (match_operand:SI 0 "s_register_operand" "=r")
1515 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1516 (match_operand:SI 1 "s_register_operand" "r")))]
1518 "orn%?\\t%0, %1, %2"
1519 [(set_attr "predicable" "yes")
1520 (set_attr "type" "logic_reg")]
1523 (define_insn "*orsi_not_shiftsi_si"
1524 [(set (match_operand:SI 0 "s_register_operand" "=r")
1525 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1526 [(match_operand:SI 2 "s_register_operand" "r")
1527 (match_operand:SI 3 "const_int_operand" "M")]))
1528 (match_operand:SI 1 "s_register_operand" "r")))]
1530 "orn%?\\t%0, %1, %2%S4"
1531 [(set_attr "predicable" "yes")
1532 (set_attr "shift" "2")
1533 (set_attr "type" "alu_shift_imm")]
1537 [(set (match_operand:CC_NZ 0 "cc_register" "")
1538 (compare:CC_NZ (zero_extract:SI
1539 (match_operand:SI 1 "low_register_operand" "")
1541 (match_operand:SI 2 "const_int_operand" ""))
1543 (match_scratch:SI 3 "l")
1545 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1546 [(match_dup 0) (const_int 0)])
1547 (match_operand 5 "" "")
1548 (match_operand 6 "" "")))]
1550 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1551 && peep2_reg_dead_p (2, operands[0])"
1552 [(parallel [(set (match_dup 0)
1553 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1555 (clobber (match_dup 3))])
1557 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1558 (match_dup 5) (match_dup 6)))]
1560 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1561 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1562 VOIDmode, operands[0], const0_rtx);
1566 [(set (match_operand:CC_NZ 0 "cc_register" "")
1567 (compare:CC_NZ (zero_extract:SI
1568 (match_operand:SI 1 "low_register_operand" "")
1569 (match_operand:SI 2 "const_int_operand" "")
1572 (match_scratch:SI 3 "l")
1574 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1575 [(match_dup 0) (const_int 0)])
1576 (match_operand 5 "" "")
1577 (match_operand 6 "" "")))]
1579 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1580 && peep2_reg_dead_p (2, operands[0])"
1581 [(parallel [(set (match_dup 0)
1582 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1584 (clobber (match_dup 3))])
1586 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1587 (match_dup 5) (match_dup 6)))]
1589 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1592 ;; Define the subtract-one-and-jump insns so loop.c
1593 ;; knows what to generate.
1594 (define_expand "doloop_end"
1595 [(use (match_operand 0 "" "")) ; loop pseudo
1596 (use (match_operand 1 "" ""))] ; label
1600 /* Currently SMS relies on the do-loop pattern to recognize loops
1601 where (1) the control part consists of all insns defining and/or
1602 using a certain 'count' register and (2) the loop count can be
1603 adjusted by modifying this register prior to the loop.
1604 ??? The possible introduction of a new block to initialize the
1605 new IV can potentially affect branch optimizations.
1607 Also used to implement the low over head loops feature, which is part of
1608 the Armv8.1-M Mainline Low Overhead Branch (LOB) extension. */
1609 if (optimize > 0 && (flag_modulo_sched || TARGET_HAVE_LOB))
1618 if (GET_MODE (operands[0]) != SImode)
1623 /* Low over head loop instructions require the first operand to be LR. */
1624 if (TARGET_HAVE_LOB && arm_target_insn_ok_for_lob (operands [1]))
1625 s0 = gen_rtx_REG (SImode, LR_REGNUM);
1628 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1630 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1632 cmp = XVECEXP (PATTERN (insn), 0, 0);
1633 cc_reg = SET_DEST (cmp);
1634 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1635 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1636 emit_jump_insn (gen_rtx_SET (pc_rtx,
1637 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1645 (define_insn "*clear_apsr"
1646 [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1647 (clobber (reg:CC CC_REGNUM))]
1648 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1650 [(set_attr "predicable" "yes")]
1653 ;; The operands are validated through the clear_multiple_operation
1654 ;; match_parallel predicate rather than through constraints so enable it only
1656 (define_insn "*clear_multiple"
1657 [(match_parallel 0 "clear_multiple_operation"
1658 [(set (match_operand:SI 1 "register_operand" "")
1660 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1663 int i, num_saves = XVECLEN (operands[0], 0);
1665 strcpy (pattern, \"clrm%?\\t{\");
1666 for (i = 0; i < num_saves; i++)
1668 if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1670 strcat (pattern, \"APSR\");
1675 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1676 if (i < num_saves - 1)
1677 strcat (pattern, \", %|\");
1679 strcat (pattern, \"}\");
1680 output_asm_insn (pattern, operands);
1683 [(set_attr "predicable" "yes")]
1686 (define_insn "thumb2_asrl"
1687 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1688 (ashiftrt:DI (match_dup 0)
1689 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1691 "asrl%?\\t%Q0, %R0, %1"
1692 [(set_attr "predicable" "yes")])
1694 (define_insn "thumb2_lsll"
1695 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1696 (ashift:DI (match_dup 0)
1697 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1699 "lsll%?\\t%Q0, %R0, %1"
1700 [(set_attr "predicable" "yes")])
1702 (define_insn "thumb2_lsrl"
1703 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1704 (lshiftrt:DI (match_dup 0)
1705 (match_operand:SI 1 "long_shift_imm" "Pg")))]
1707 "lsrl%?\\t%Q0, %R0, %1"
1708 [(set_attr "predicable" "yes")])
1710 ;; Originally expanded by 'doloop_end'.
1711 (define_insn "*doloop_end_internal"
1712 [(parallel [(set (pc)
1714 (ne (reg:SI LR_REGNUM) (const_int 1))
1715 (label_ref (match_operand 0 "" ""))
1717 (set (reg:SI LR_REGNUM)
1718 (plus:SI (reg:SI LR_REGNUM) (const_int -1)))])]
1719 "TARGET_32BIT && TARGET_HAVE_LOB"
1722 (define_expand "doloop_begin"
1723 [(match_operand 0 "" "")
1724 (match_operand 1 "" "")]
1725 "TARGET_32BIT && TARGET_HAVE_LOB"
1727 if (REGNO (operands[0]) == LR_REGNUM)
1729 emit_insn (gen_dls_insn (operands[0]));
1736 (define_insn "dls_insn"
1737 [(set (reg:SI LR_REGNUM)
1738 (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))]
1739 "TARGET_32BIT && TARGET_HAVE_LOB"