[PR testsuite/116860] Testsuite adjustment for recently added tests
[official-gcc.git] / gcc / config / arm / thumb2.md
blob172c974b3dacf27ff6d7259765d7f12f3dc5affe
1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2025 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery, LLC.
4 ;;
5 ;; This file is part of GCC.
6 ;;
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)
10 ;; any later version.
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))]
34    "TARGET_THUMB2"
35    "#"
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))
41               (set (match_dup 0)
42                    (match_dup 2)))]
43   ""
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))]
55   "TARGET_THUMB2"
56   "#"
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))
62               (set (match_dup 0)
63                    (match_dup 2)))]
64   ""
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))]
76   "TARGET_THUMB2"
77   "#"
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))
83               (set (match_dup 0)
84                    (match_dup 2)))]
85   ""
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))]
97   "TARGET_THUMB2"
98   "#"
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))
104               (set (match_dup 0)
105                    (match_dup 2)))]
106   ""
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))]
117   "TARGET_THUMB2"
118   "#"
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"
123   [(const_int 0)]
124   {
125     if (REGNO(operands[0]) == REGNO(operands[1]))
126       {
127        rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
129        emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
130                                                         const0_rtx)));
131        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
132                                     (gen_rtx_LT (SImode,
133                                                  cc_reg,
134                                                  const0_rtx)),
135                                     (gen_rtx_SET (operands[0],
136                                                   (gen_rtx_MINUS (SImode,
137                                                                   const0_rtx,
138                                                                   operands[1]))))));
139       }
140     else
141       {
142         emit_insn (gen_rtx_SET (operands[0],
143                                 gen_rtx_XOR (SImode,
144                                              gen_rtx_ASHIFTRT (SImode,
145                                                                operands[1],
146                                                                GEN_INT (31)),
147                                              operands[1])));
148         emit_insn (gen_rtx_SET (operands[0],
149                                 gen_rtx_MINUS (SImode,
150                                                operands[0],
151                                                gen_rtx_ASHIFTRT (SImode,
152                                                                  operands[1],
153                                                                  GEN_INT (31)))));
154       }
155     DONE;
156   }
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))]
170   "TARGET_THUMB2"
171   "#"
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"
176   [(const_int 0)]
177   {
178     if (REGNO(operands[0]) == REGNO(operands[1]))
179       {
180        rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
182        emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
183                                                         const0_rtx)));
184        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
185                                     (gen_rtx_GT (SImode,
186                                                  cc_reg,
187                                                  const0_rtx)),
188                                     (gen_rtx_SET (operands[0],
189                                                   (gen_rtx_MINUS (SImode,
190                                                                   const0_rtx,
191                                                                   operands[1]))))));
192       }
193     else
194       {
195         emit_insn (gen_rtx_SET (operands[0],
196                                 gen_rtx_XOR (SImode,
197                                              gen_rtx_ASHIFTRT (SImode,
198                                                                operands[1],
199                                                                GEN_INT (31)),
200                                              operands[1])));
201         emit_insn (gen_rtx_SET (operands[0],
202                                 gen_rtx_MINUS (SImode,
203                                                gen_rtx_ASHIFTRT (SImode,
204                                                                  operands[1],
205                                                                  GEN_INT (31)),
206                                                operands[0])));
207       }
208     DONE;
209   }
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)"
224   "pop\t{%0}"
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)
243     {
244     case 0:
245     case 1:
246     case 2:
247       return \"mov%?\\t%0, %1\";
248     case 3: return \"mvn%?\\t%0, #%B1\";
249     case 4: return \"movw%?\\t%0, %1\";
250     case 5:
251       /* Cannot load it directly, split to load it via MOV / MOVT.  */
252       if (!MEM_P (operands[1]) && arm_disable_literal_pool)
253         return \"#\";
254       return \"ldr%?\\t%0, %1\";
255     case 6: return \"str%?\\t%1, %0\";
256     default: gcc_unreachable ();
257     }
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")
270                             (const_int 4)
271                             (match_operand 3 "" "")]
272                            UNSPEC_PIC_BASE)))
273    (clobber (match_scratch:SI 1 "=X,l,X,r"))]
274   "TARGET_THUMB2"
275   "*
276   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
277                              INTVAL (operands[3]));
278   return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
279   "
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"))]
289   "TARGET_THUMB2
290   && (register_operand (operands[0], HImode)
291      || register_operand (operands[1], HImode))"
292   "@
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"))]
316   "TARGET_THUMB2
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)]))]
326   "TARGET_THUMB2"
327   "#"   ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
328   "TARGET_THUMB2"
329   [(set (match_dup 0)
330         (if_then_else:SI (match_dup 1)
331                          (const_int 1)
332                          (const_int 0)))]
333   ""
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)])))]
344   "TARGET_THUMB2
345    && !arm_restrict_it
346    && !arm_borrow_operation (operands[1], SImode)"
347   "#"   ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
348   "&& true"
349   [(set (match_dup 0)
350         (if_then_else:SI (match_dup 1)
351                          (match_dup 3)
352                          (const_int 0)))]
353   {
354     operands[3] = GEN_INT (~0);
355   }
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)])))]
365   "TARGET_THUMB2
366    && arm_restrict_it
367    && !arm_borrow_operation (operands[1], SImode)"
368   "#"   ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\"
369   "&& reload_completed"
370   [(set (match_dup 0)
371         (match_dup 3))
372    (cond_exec (match_dup 4)
373               (set (match_dup 0)
374                    (const_int 0)))]
375   {
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);
382     else
383       rc = reverse_condition (rc);
384     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
386   }
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"
398   "&& true"
399   [(set (match_dup 0)
400         (if_then_else:SI (match_dup 1)
401                          (match_dup 3)
402                          (match_dup 4)))]
403   {
404     operands[3] = GEN_INT (~1);
405     operands[4] = GEN_INT (~0);
406   }
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"
419   [(set (match_dup 0)
420         (match_dup 3))
421    (cond_exec (match_dup 4)
422               (set (match_dup 0)
423                    (ashift:SI (match_dup 0)
424                               (const_int 1))))]
425   {
426     operands[3] = GEN_INT (~0);
427     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
428                                   VOIDmode, operands[2], const0_rtx);
429   }
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")
437         (if_then_else:SI
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")))]
442   "TARGET_THUMB2"
443   "@
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
450    #
451    #
452    #
453    #
454    #
455    #"
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"
463   [(const_int 0)]
464   {
465     enum rtx_code rev_code;
466     machine_mode mode;
467     rtx rev_cond;
469     emit_insn (gen_rtx_COND_EXEC (VOIDmode,
470                                   operands[3],
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);
476     else
477       rev_code = reverse_condition (rev_code);
479     rev_cond = gen_rtx_fmt_ee (rev_code,
480                                VOIDmode,
481                                gen_rtx_REG (mode, CC_REGNUM),
482                                const0_rtx);
483     emit_insn (gen_rtx_COND_EXEC (VOIDmode,
484                                   rev_cond,
485                                   gen_rtx_SET (operands[0], operands[2])));
486     DONE;
487   }
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"
521   "@
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))]
534   "TARGET_THUMB2"
535   "blx%?\\t%0"
536   [(set_attr "type" "call")]
539 (define_insn "*nonsecure_call_reg_thumb2_fpcxt"
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 && TARGET_HAVE_FPCXT_CMSE"
546   "blxns\\t%0"
547   [(set_attr "length" "4")
548    (set_attr "type" "call")]
551 (define_insn "*nonsecure_call_reg_thumb2"
552   [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
553                     UNSPEC_NONSECURE_MEM)
554          (match_operand 0 "" ""))
555    (use (match_operand 1 "" ""))
556    (clobber (reg:SI LR_REGNUM))]
557   "TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE"
558   "bl\\t__gnu_cmse_nonsecure_call"
559   [(set_attr "length" "4")
560    (set_attr "type" "call")]
563 (define_insn "*call_value_reg_thumb2"
564   [(set (match_operand 0 "" "")
565         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
566               (match_operand 2 "" "")))
567    (use (match_operand 3 "" ""))
568    (clobber (reg:SI LR_REGNUM))]
569   "TARGET_THUMB2"
570   "blx\\t%1"
571   [(set_attr "type" "call")]
574 (define_insn "*nonsecure_call_value_reg_thumb2_fpcxt"
575   [(set (match_operand 0 "" "")
576         (call
577          (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
578                     UNSPEC_NONSECURE_MEM)
579          (match_operand 2 "" "")))
580    (use (match_operand 3 "" ""))
581    (clobber (reg:SI LR_REGNUM))]
582   "TARGET_THUMB2 && use_cmse && TARGET_HAVE_FPCXT_CMSE"
583   "blxns\\t%1"
584   [(set_attr "length" "4")
585    (set_attr "type" "call")]
588 (define_insn "*nonsecure_call_value_reg_thumb2"
589   [(set (match_operand 0 "" "")
590         (call
591          (unspec:SI [(mem:SI (reg:SI R4_REGNUM))] UNSPEC_NONSECURE_MEM)
592          (match_operand 1 "" "")))
593    (use (match_operand 2 "" ""))
594    (clobber (reg:SI LR_REGNUM))]
595   "TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE"
596   "bl\\t__gnu_cmse_nonsecure_call"
597   [(set_attr "length" "4")
598    (set_attr "type" "call")]
601 (define_insn "*thumb2_indirect_jump"
602   [(set (pc)
603         (match_operand:SI 0 "register_operand" "l*r"))]
604   "TARGET_THUMB2"
605   "bx\\t%0"
606   [(set_attr "conds" "clob")
607    (set_attr "type" "branch")]
609 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
610 ;; addresses will have the thumb bit set correctly.
613 (define_insn_and_split "*thumb2_and_scc"
614   [(set (match_operand:SI 0 "s_register_operand" "=Ts")
615         (and:SI (match_operator:SI 1 "arm_comparison_operator"
616                  [(match_operand 2 "cc_register" "") (const_int 0)])
617                 (match_operand:SI 3 "s_register_operand" "r")))]
618   "TARGET_THUMB2"
619   "#"   ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
620   "&& reload_completed"
621   [(set (match_dup 0)
622         (and:SI (match_dup 3) (const_int 1)))
623    (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
624   {
625     machine_mode mode = GET_MODE (operands[2]);
626     enum rtx_code rc = GET_CODE (operands[1]);
628     if (mode == CCFPmode || mode == CCFPEmode)
629       rc = reverse_condition_maybe_unordered (rc);
630     else
631       rc = reverse_condition (rc);
632     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
633   }
634   [(set_attr "conds" "use")
635    (set_attr "type" "multiple")
636    (set (attr "length") (if_then_else (match_test "arm_restrict_it")
637                                       (const_int 8)
638                                       (const_int 10)))]
641 (define_insn_and_split "*thumb2_ior_scc"
642   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
643         (ior:SI (match_operator:SI 1 "arm_comparison_operator"
644                  [(match_operand 2 "cc_register" "") (const_int 0)])
645                 (match_operand:SI 3 "s_register_operand" "0,?r")))]
646   "TARGET_THUMB2 && !arm_restrict_it"
647   "@
648    it\\t%d1\;orr%d1\\t%0, %3, #1
649    #"
650    ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
651    "&& reload_completed
652     && REGNO (operands [0]) != REGNO (operands[3])"
653    [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
654     (cond_exec (match_dup 4) (set (match_dup 0)
655                                   (ior:SI (match_dup 3) (const_int 1))))]
656   {
657     machine_mode mode = GET_MODE (operands[2]);
658     enum rtx_code rc = GET_CODE (operands[1]);
660     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
661     if (mode == CCFPmode || mode == CCFPEmode)
662       rc = reverse_condition_maybe_unordered (rc);
663     else
664       rc = reverse_condition (rc);
665     operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
666   }
667   [(set_attr "conds" "use")
668    (set_attr "length" "6,10")
669    (set_attr "type" "multiple")]
672 (define_insn_and_split "*thumb2_ior_scc_strict_it"
673   [(set (match_operand:SI 0 "s_register_operand" "=&r")
674         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
675                  [(match_operand 3 "cc_register" "") (const_int 0)])
676                 (match_operand:SI 1 "s_register_operand" "r")))]
677   "TARGET_THUMB2 && arm_restrict_it"
678   "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
679   "&& reload_completed"
680   [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
681    (cond_exec (match_dup 4)
682      (set (match_dup 0) (match_dup 1)))]
683   {
684     machine_mode mode = GET_MODE (operands[3]);
685     rtx_code rc = GET_CODE (operands[2]);
687     if (mode == CCFPmode || mode == CCFPEmode)
688       rc = reverse_condition_maybe_unordered (rc);
689     else
690       rc = reverse_condition (rc);
691     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
692   }
693   [(set_attr "conds" "use")
694    (set_attr "length" "8")
695    (set_attr "type" "multiple")]
698 (define_insn "*thumb2_cond_move"
699   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
700         (if_then_else:SI (match_operator 3 "equality_operator"
701                           [(match_operator 4 "arm_comparison_operator"
702                             [(match_operand 5 "cc_register" "") (const_int 0)])
703                            (const_int 0)])
704                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
705                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
706   "TARGET_THUMB2"
707   "*
708     if (GET_CODE (operands[3]) == NE)
709       {
710         if (which_alternative != 1)
711           output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
712         if (which_alternative != 0)
713           output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
714         return \"\";
715       }
716     switch (which_alternative)
717       {
718       case 0:
719         output_asm_insn (\"it\\t%d4\", operands);
720         break;
721       case 1:
722         output_asm_insn (\"it\\t%D4\", operands);
723         break;
724       case 2:
725         if (arm_restrict_it)
726           output_asm_insn (\"it\\t%D4\", operands);
727         else
728           output_asm_insn (\"ite\\t%D4\", operands);
729         break;
730       default:
731         abort();
732       }
733     if (which_alternative != 0)
734       {
735         output_asm_insn (\"mov%D4\\t%0, %1\", operands);
736         if (arm_restrict_it && which_alternative == 2)
737           output_asm_insn (\"it\\t%d4\", operands);
738       }
739     if (which_alternative != 1)
740       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
741     return \"\";
742   "
743   [(set_attr "conds" "use")
744    (set_attr "length" "6,6,10")
745    (set_attr "type" "multiple")]
748 (define_insn "*thumb2_cond_arith"
749   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
750         (match_operator:SI 5 "shiftable_operator"
751          [(match_operator:SI 4 "arm_comparison_operator"
752            [(match_operand:SI 2 "s_register_operand" "r,r")
753             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
754           (match_operand:SI 1 "s_register_operand" "0,?r")]))
755    (clobber (reg:CC CC_REGNUM))]
756   "TARGET_THUMB2 && !arm_restrict_it"
757   "*
758     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
759       return \"%i5\\t%0, %1, %2, lsr #31\";
761     output_asm_insn (\"cmp\\t%2, %3\", operands);
763     if (GET_CODE (operands[5]) == PLUS && TARGET_COND_ARITH)
764       return \"cinc\\t%0, %1, %d4\";
766     if (GET_CODE (operands[5]) == AND)
767       {
768         output_asm_insn (\"ite\\t%D4\", operands);
769         output_asm_insn (\"mov%D4\\t%0, #0\", operands);
770       }
771     else if (GET_CODE (operands[5]) == MINUS)
772       {
773         output_asm_insn (\"ite\\t%D4\", operands);
774         output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
775       }
776     else if (which_alternative != 0)
777       {
778         output_asm_insn (\"ite\\t%D4\", operands);
779         output_asm_insn (\"mov%D4\\t%0, %1\", operands);
780       }
781     else
782       output_asm_insn (\"it\\t%d4\", operands);
783     return \"%i5%d4\\t%0, %1, #1\";
784   "
785   [(set_attr "conds" "clob")
786    (set_attr "length" "14")
787    (set_attr "type" "multiple")]
790 (define_insn_and_split "*thumb2_cond_arith_strict_it"
791   [(set (match_operand:SI 0 "s_register_operand" "=l")
792         (match_operator:SI 5 "shiftable_operator_strict_it"
793          [(match_operator:SI 4 "arm_comparison_operator"
794            [(match_operand:SI 2 "s_register_operand" "r")
795             (match_operand:SI 3 "arm_rhs_operand" "rI")])
796           (match_operand:SI 1 "s_register_operand" "0")]))
797    (clobber (reg:CC CC_REGNUM))]
798   "TARGET_THUMB2 && arm_restrict_it"
799   "#"
800   "&& reload_completed"
801   [(const_int 0)]
802   {
803     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
804       {
805         /*  %i5 %0, %1, %2, lsr #31  */
806         rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
807         rtx op = NULL_RTX;
809         switch (GET_CODE (operands[5]))
810           {
811           case AND:
812             op = gen_rtx_AND (SImode, shifted_op, operands[1]);
813             break;
814            case PLUS:
815             op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
816             break;
817           default: gcc_unreachable ();
818           }
819         emit_insn (gen_rtx_SET (operands[0], op));
820         DONE;
821       }
823     /*  "cmp  %2, %3"  */
824     emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
825                             gen_rtx_COMPARE (CCmode, operands[2],
826                                              operands[3])));
828     if (GET_CODE (operands[5]) == AND)
829       {
830         /*  %i5  %0, %1, #1
831             it%D4
832             mov%D4  %0, #0  */
833         enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
834         emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
835                                                           GEN_INT (1))));
836         emit_insn (gen_rtx_COND_EXEC (VOIDmode,
837                                       gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
838                                       gen_rtx_SET (operands[0], const0_rtx)));
839         DONE;
840       }
841     else
842       {
843         /*  it\\t%d4
844             %i5%d4\\t%0, %1, #1   */
845         emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
846                                                                 VOIDmode,
847                                                                 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
848                                                 gen_rtx_SET (operands[0],
849                                                             gen_rtx_PLUS (SImode,
850                                                                           operands[1],
851                                                                           GEN_INT (1)))));
852         DONE;
853       }
854      FAIL;
855   }
856   [(set_attr "conds" "clob")
857    (set_attr "length" "12")
858    (set_attr "type" "multiple")]
861 (define_insn "*thumb2_cond_sub"
862   [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
863         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
864                   (match_operator:SI 4 "arm_comparison_operator"
865                    [(match_operand:SI 2 "s_register_operand" "r,r")
866                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
867    (clobber (reg:CC CC_REGNUM))]
868   "TARGET_THUMB2"
869   "*
870     output_asm_insn (\"cmp\\t%2, %3\", operands);
871     if (which_alternative != 0)
872       {
873         if (arm_restrict_it)
874           {
875             output_asm_insn (\"mov\\t%0, %1\", operands);
876             output_asm_insn (\"it\\t%d4\", operands);
877           }
878         else
879         {
880           output_asm_insn (\"ite\\t%D4\", operands);
881           output_asm_insn (\"mov%D4\\t%0, %1\", operands);
882         }
883       }
884     else
885       output_asm_insn (\"it\\t%d4\", operands);
886     return \"sub%d4\\t%0, %1, #1\";
887   "
888   [(set_attr "conds" "clob")
889    (set_attr "length" "10,14")
890    (set_attr "type" "multiple")]
893 (define_insn_and_split "*thumb2_negscc"
894   [(set (match_operand:SI 0 "s_register_operand" "=Ts")
895         (neg:SI (match_operator 3 "arm_comparison_operator"
896                  [(match_operand:SI 1 "s_register_operand" "r")
897                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
898    (clobber (reg:CC CC_REGNUM))]
899   "TARGET_THUMB2 && !TARGET_COND_ARITH"
900   "#"
901   "&& reload_completed"
902   [(const_int 0)]
903   {
904     rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
906     if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
907       {
908         /* Emit asr\\t%0, %1, #31 */
909         emit_insn (gen_rtx_SET (operands[0],
910                                 gen_rtx_ASHIFTRT (SImode,
911                                                   operands[1],
912                                                   GEN_INT (31))));
913         DONE;
914       }
915     else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
916       {
917         /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
918         if (CONST_INT_P (operands[2]))
919           emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
920                                         gen_int_mode (-INTVAL (operands[2]),
921                                                       SImode)));
922         else
923           emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
925         emit_insn (gen_rtx_COND_EXEC (VOIDmode,
926                                       gen_rtx_NE (SImode,
927                                                   cc_reg,
928                                                   const0_rtx),
929                                       gen_rtx_SET (operands[0],
930                                                    GEN_INT (~0))));
931         DONE;
932       }
933     else
934       {
935        /* Emit:  cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
936        enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
937        machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
938        rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
940        emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
941                                                         operands[2])));
943        emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
945        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
946                                      gen_rtx_fmt_ee (rc,
947                                                      VOIDmode,
948                                                      tmp1,
949                                                      const0_rtx),
950                                      gen_rtx_SET (operands[0], const0_rtx)));
951        DONE;
952       }
953     FAIL;
954   }
955   [(set_attr "conds" "clob")
956    (set_attr "length" "14")
957    (set_attr "type" "multiple")]
960 (define_insn "*thumb2_csinv"
961   [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
962         (if_then_else:SI
963          (match_operand 1 "arm_comparison_operation" "")
964          (not:SI (match_operand:SI 2 "arm_general_register_operand" "r, r"))
965          (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
966   "TARGET_COND_ARITH"
967   "@
968    csinv\\t%0, %3, %2, %D1
969    csinv\\t%0, zr, %2, %D1"
970   [(set_attr "type" "csel")
971    (set_attr "predicable" "no")]
974 (define_insn "*thumb2_csinc"
975   [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
976         (if_then_else:SI
977          (match_operand 1 "arm_comparison_operation" "")
978          (plus:SI (match_operand:SI 2 "arm_general_register_operand" "r, r")
979                   (const_int 1))
980          (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
981   "TARGET_COND_ARITH"
982   "@
983    csinc\\t%0, %3, %2, %D1
984    csinc\\t%0, zr, %2, %D1"
985   [(set_attr "type" "csel")
986    (set_attr "predicable" "no")]
989 (define_insn "*thumb2_csneg"
990   [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
991         (if_then_else:SI
992          (match_operand 1 "arm_comparison_operation" "")
993          (neg:SI (match_operand:SI 2 "arm_general_register_operand" "r, r"))
994          (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
995   "TARGET_COND_ARITH"
996   "@
997    csneg\\t%0, %3, %2, %D1
998    csneg\\t%0, zr, %2, %D1"
999   [(set_attr "type" "csel")
1000    (set_attr "predicable" "no")]
1003 (define_insn "*thumb2_movcond"
1004   [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
1005         (if_then_else:SI
1006          (match_operator 5 "arm_comparison_operator"
1007           [(match_operand:SI 3 "s_register_operand" "r,r,r")
1008            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
1009          (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
1010          (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
1011    (clobber (reg:CC CC_REGNUM))]
1012   "TARGET_THUMB2 && !TARGET_COND_ARITH"
1013   "*
1014   if (GET_CODE (operands[5]) == LT
1015       && (operands[4] == const0_rtx))
1016     {
1017       if (which_alternative != 1 && REG_P (operands[1]))
1018         {
1019           if (operands[2] == const0_rtx)
1020             return \"and\\t%0, %1, %3, asr #31\";
1021           return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
1022         }
1023       else if (which_alternative != 0 && REG_P (operands[2]))
1024         {
1025           if (operands[1] == const0_rtx)
1026             return \"bic\\t%0, %2, %3, asr #31\";
1027           return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
1028         }
1029       /* The only case that falls through to here is when both ops 1 & 2
1030          are constants.  */
1031     }
1033   if (GET_CODE (operands[5]) == GE
1034       && (operands[4] == const0_rtx))
1035     {
1036       if (which_alternative != 1 && REG_P (operands[1]))
1037         {
1038           if (operands[2] == const0_rtx)
1039             return \"bic\\t%0, %1, %3, asr #31\";
1040           return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
1041         }
1042       else if (which_alternative != 0 && REG_P (operands[2]))
1043         {
1044           if (operands[1] == const0_rtx)
1045             return \"and\\t%0, %2, %3, asr #31\";
1046           return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
1047         }
1048       /* The only case that falls through to here is when both ops 1 & 2
1049          are constants.  */
1050     }
1051   if (CONST_INT_P (operands[4])
1052       && !const_ok_for_arm (INTVAL (operands[4])))
1053     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
1054   else
1055     output_asm_insn (\"cmp\\t%3, %4\", operands);
1056   switch (which_alternative)
1057     {
1058     case 0:
1059       output_asm_insn (\"it\\t%D5\", operands);
1060       break;
1061     case 1:
1062       output_asm_insn (\"it\\t%d5\", operands);
1063       break;
1064     case 2:
1065       if (arm_restrict_it)
1066         {
1067           output_asm_insn (\"mov\\t%0, %1\", operands);
1068           output_asm_insn (\"it\\t%D5\", operands);
1069         }
1070       else
1071         output_asm_insn (\"ite\\t%d5\", operands);
1072       break;
1073     default:
1074       abort();
1075     }
1076   if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1077     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1078   if (which_alternative != 1)
1079     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1080   return \"\";
1081   "
1082   [(set_attr "conds" "clob")
1083    (set_attr "length" "10,10,14")
1084    (set_attr "type" "multiple")]
1087 ;; Zero and sign extension instructions.
1089 ;; All supported Thumb2 implementations are armv6, so only that case is
1090 ;; provided.
1091 (define_insn "*thumb2_extendqisi_v6"
1092   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1093         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1094   "TARGET_THUMB2 && arm_arch6"
1095   "@
1096    sxtb%?\\t%0, %1
1097    ldrsb%?\\t%0, %1"
1098   [(set_attr "type" "extend,load_byte")
1099    (set_attr "predicable" "yes")
1100    (set_attr "pool_range" "*,4094")
1101    (set_attr "neg_pool_range" "*,250")]
1104 (define_insn "*thumb2_zero_extendhisi2_v6"
1105   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1106         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1107   "TARGET_THUMB2 && arm_arch6"
1108   "@
1109    uxth%?\\t%0, %1
1110    ldrh%?\\t%0, %1"
1111   [(set_attr "type" "extend,load_byte")
1112    (set_attr "predicable" "yes")
1113    (set_attr "pool_range" "*,4094")
1114    (set_attr "neg_pool_range" "*,250")]
1117 (define_insn "thumb2_zero_extendqisi2_v6"
1118   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1119         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1120   "TARGET_THUMB2 && arm_arch6"
1121   "@
1122    uxtb%?\\t%0, %1
1123    ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1124   [(set_attr "type" "extend,load_byte")
1125    (set_attr "predicable" "yes")
1126    (set_attr "pool_range" "*,4094")
1127    (set_attr "neg_pool_range" "*,250")]
1130 (define_expand "thumb2_casesi_internal"
1131   [(parallel [(set (pc)
1132                (if_then_else
1133                 (leu (match_operand:SI 0 "s_register_operand")
1134                      (match_operand:SI 1 "arm_rhs_operand"))
1135                 (match_dup 4)
1136                 (label_ref:SI (match_operand 3 ""))))
1137               (clobber (reg:CC CC_REGNUM))
1138               (clobber (match_scratch:SI 5))
1139               (use (label_ref:SI (match_operand 2 "")))])]
1140   "TARGET_THUMB2 && !flag_pic"
1142   operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1143   operands[4] = gen_rtx_PLUS (SImode, operands[4],
1144                               gen_rtx_LABEL_REF (SImode, operands[2]));
1145   operands[4] = gen_rtx_MEM (SImode, operands[4]);
1146   MEM_READONLY_P (operands[4]) = 1;
1147   MEM_NOTRAP_P (operands[4]) = 1;
1150 (define_insn "*thumb2_casesi_internal"
1151   [(parallel [(set (pc)
1152                (if_then_else
1153                 (leu (match_operand:SI 0 "s_register_operand" "r")
1154                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
1155                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1156                                  (label_ref:SI (match_operand 2 "" ""))))
1157                 (label_ref:SI (match_operand 3 "" ""))))
1158               (clobber (reg:CC CC_REGNUM))
1159               (clobber (match_scratch:SI 4 "=&r"))
1160               (use (label_ref:SI (match_dup 2)))])]
1161   "TARGET_THUMB2 && !flag_pic"
1162   "* return thumb2_output_casesi(operands);"
1163   [(set_attr "conds" "clob")
1164    (set_attr "length" "16")
1165    (set_attr "type" "multiple")]
1168 (define_expand "thumb2_casesi_internal_pic"
1169   [(parallel [(set (pc)
1170                (if_then_else
1171                 (leu (match_operand:SI 0 "s_register_operand")
1172                      (match_operand:SI 1 "arm_rhs_operand"))
1173                 (match_dup 4)
1174                 (label_ref:SI (match_operand 3 ""))))
1175               (clobber (reg:CC CC_REGNUM))
1176               (clobber (match_scratch:SI 5))
1177               (clobber (match_scratch:SI 6))
1178               (use (label_ref:SI (match_operand 2 "")))])]
1179   "TARGET_THUMB2 && flag_pic"
1181   operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1182   operands[4] = gen_rtx_PLUS (SImode, operands[4],
1183                               gen_rtx_LABEL_REF (SImode, operands[2]));
1184   operands[4] = gen_rtx_MEM (SImode, operands[4]);
1185   MEM_READONLY_P (operands[4]) = 1;
1186   MEM_NOTRAP_P (operands[4]) = 1;
1189 (define_insn "*thumb2_casesi_internal_pic"
1190   [(parallel [(set (pc)
1191                (if_then_else
1192                 (leu (match_operand:SI 0 "s_register_operand" "r")
1193                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
1194                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1195                                  (label_ref:SI (match_operand 2 "" ""))))
1196                 (label_ref:SI (match_operand 3 "" ""))))
1197               (clobber (reg:CC CC_REGNUM))
1198               (clobber (match_scratch:SI 4 "=&r"))
1199               (clobber (match_scratch:SI 5 "=r"))
1200               (use (label_ref:SI (match_dup 2)))])]
1201   "TARGET_THUMB2 && flag_pic"
1202   "* return thumb2_output_casesi(operands);"
1203   [(set_attr "conds" "clob")
1204    (set_attr "length" "20")
1205    (set_attr "type" "multiple")]
1208 (define_insn "*thumb2_return"
1209   [(simple_return)]
1210   "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1211   "* return output_return_instruction (const_true_rtx, true, false, true);"
1212   [(set_attr "type" "branch")
1213    (set_attr "length" "4")]
1216 (define_insn "*thumb2_cmse_entry_return"
1217   [(simple_return)]
1218   "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1219   "* return output_return_instruction (const_true_rtx, true, false, true);"
1220   [(set_attr "type" "branch")
1221    ; This is a return from a cmse_nonsecure_entry function so code will be
1222    ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1223    ; we adapt the length accordingly.
1224    (set (attr "length")
1225      (if_then_else (match_test "TARGET_HARD_FLOAT")
1226       (const_int 34)
1227       (const_int 8)))
1228    ; We do not support predicate execution of returns from cmse_nonsecure_entry
1229    ; functions because we need to clear the APSR.  Since predicable has to be
1230    ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1231    ; functions.
1232    (set_attr "predicable" "no")]
1235 (define_insn_and_split "thumb2_eh_return"
1236   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1237                     VUNSPEC_EH_RETURN)
1238    (clobber (match_scratch:SI 1 "=&r"))]
1239   "TARGET_THUMB2"
1240   "#"
1241   "&& reload_completed"
1242   [(const_int 0)]
1243   "
1244   {
1245     thumb_set_return_address (operands[0], operands[1]);
1246     DONE;
1247   }"
1250 (define_insn "*thumb2_alusi3_short"
1251   [(set (match_operand:SI          0 "s_register_operand" "=l")
1252         (match_operator:SI 3 "thumb_16bit_operator"
1253          [(match_operand:SI 1 "s_register_operand" "0")
1254           (match_operand:SI 2 "s_register_operand" "l")]))
1255    (clobber (reg:CC CC_REGNUM))]
1256   "TARGET_THUMB2 && reload_completed
1257    && GET_CODE(operands[3]) != PLUS
1258    && GET_CODE(operands[3]) != MINUS"
1259   "%I3%!\\t%0, %1, %2"
1260   [(set_attr "predicable" "yes")
1261    (set_attr "length" "2")
1262    (set_attr "type" "alu_sreg")]
1265 (define_insn "*thumb2_shiftsi3_short"
1266   [(set (match_operand:SI   0 "low_register_operand" "=l,l")
1267         (match_operator:SI  3 "shift_operator"
1268          [(match_operand:SI 1 "low_register_operand"  "0,l")
1269           (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1270    (clobber (reg:CC CC_REGNUM))]
1271   "TARGET_THUMB2 && reload_completed
1272    && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1273        || REG_P (operands[2]))"
1274   "* return arm_output_shift(operands, 2);"
1275   [(set_attr "predicable" "yes")
1276    (set_attr "shift" "1")
1277    (set_attr "length" "2")
1278    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1279                         (if_then_else (match_operand 3 "alu_shift_operator_lsl_1_to_4")
1280                           (const_string "alu_shift_imm_lsl_1to4")
1281                           (const_string "alu_shift_imm_other"))
1282                       (const_string "alu_shift_reg")))]
1285 (define_insn "*thumb2_mov<mode>_shortim"
1286   [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1287         (match_operand:QHSI 1 "const_int_operand" "I"))
1288    (clobber (reg:CC CC_REGNUM))]
1289   "TARGET_THUMB2 && reload_completed"
1290   "mov%!\t%0, %1"
1291   [(set_attr "predicable" "yes")
1292    (set_attr "length" "2")
1293    (set_attr "type" "mov_imm")]
1296 (define_insn "*thumb2_addsi_short"
1297   [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1298         (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1299                  (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1300    (clobber (reg:CC CC_REGNUM))]
1301   "TARGET_THUMB2 && reload_completed"
1302   "*
1303     HOST_WIDE_INT val;
1305     if (CONST_INT_P (operands[2]))
1306       val = INTVAL(operands[2]);
1307     else
1308       val = 0;
1310     /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff.  */
1311     if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1312       return \"sub%!\\t%0, %1, #%n2\";
1313     else
1314       return \"add%!\\t%0, %1, %2\";
1315   "
1316   [(set_attr "predicable" "yes")
1317    (set_attr "length" "2")
1318    (set_attr_alternative "type"
1319                          [(if_then_else (match_operand 2 "const_int_operand" "")
1320                                         (const_string "alu_imm")
1321                                         (const_string "alu_sreg"))
1322                           (const_string "alu_imm")])]
1325 (define_insn "*thumb2_subsi_short"
1326   [(set (match_operand:SI 0 "low_register_operand" "=l")
1327         (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1328                   (match_operand:SI 2 "low_register_operand" "l")))
1329    (clobber (reg:CC CC_REGNUM))]
1330   "TARGET_THUMB2 && reload_completed"
1331   "sub%!\\t%0, %1, %2"
1332   [(set_attr "predicable" "yes")
1333    (set_attr "length" "2")
1334    (set_attr "type" "alu_sreg")]
1337 (define_peephole2
1338   [(set (match_operand:CC 0 "cc_register" "")
1339         (compare:CC (match_operand:SI 1 "low_register_operand" "")
1340                     (match_operand:SI 2 "const_int_operand" "")))]
1341   "TARGET_THUMB2
1342    && peep2_reg_dead_p (1, operands[1])
1343    && satisfies_constraint_Pw (operands[2])"
1344   [(parallel
1345     [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1346      (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1347   "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1350 (define_peephole2
1351   [(match_scratch:SI 3 "l")
1352    (set (match_operand:CC 0 "cc_register" "")
1353         (compare:CC (match_operand:SI 1 "low_register_operand" "")
1354                     (match_operand:SI 2 "const_int_operand" "")))]
1355   "TARGET_THUMB2
1356    && satisfies_constraint_Px (operands[2])"
1357   [(parallel
1358     [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1359      (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1360   "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1363 (define_insn "thumb2_addsi3_compare0"
1364   [(set (reg:CC_NZ CC_REGNUM)
1365         (compare:CC_NZ
1366           (plus:SI (match_operand:SI 1 "s_register_operand" "l,  0, r")
1367                    (match_operand:SI 2 "arm_add_operand"    "lPt,Ps,rIL"))
1368           (const_int 0)))
1369    (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1370         (plus:SI (match_dup 1) (match_dup 2)))]
1371   "TARGET_THUMB2"
1372   "*
1373     HOST_WIDE_INT val;
1375     if (CONST_INT_P (operands[2]))
1376       val = INTVAL (operands[2]);
1377     else
1378       val = 0;
1380     if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1381       return \"subs\\t%0, %1, #%n2\";
1382     else
1383       return \"adds\\t%0, %1, %2\";
1384   "
1385   [(set_attr "conds" "set")
1386    (set_attr "length" "2,2,4")
1387    (set_attr_alternative "type"
1388                          [(if_then_else (match_operand 2 "const_int_operand" "")
1389                                         (const_string "alus_imm")
1390                                         (const_string "alus_sreg"))
1391                           (const_string "alus_imm")
1392                           (if_then_else (match_operand 2 "const_int_operand" "")
1393                                         (const_string "alus_imm")
1394                                         (const_string "alus_sreg"))])]
1397 (define_insn "*thumb2_addsi3_compare0_scratch"
1398   [(set (reg:CC_NZ CC_REGNUM)
1399         (compare:CC_NZ
1400           (plus:SI (match_operand:SI 0 "s_register_operand" "l,  r")
1401                    (match_operand:SI 1 "arm_add_operand"    "lPv,rIL"))
1402           (const_int 0)))]
1403   "TARGET_THUMB2"
1404   "*
1405     HOST_WIDE_INT val;
1407     if (CONST_INT_P (operands[1]))
1408       val = INTVAL (operands[1]);
1409     else
1410       val = 0;
1412     if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1413       return \"cmp\\t%0, #%n1\";
1414     else
1415       return \"cmn\\t%0, %1\";
1416   "
1417   [(set_attr "conds" "set")
1418    (set_attr "length" "2,4")
1419    (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1420                                     (const_string "alus_imm")
1421                                     (const_string "alus_sreg")))]
1424 (define_insn "*thumb2_mulsi_short"
1425   [(set (match_operand:SI 0 "low_register_operand" "=l")
1426         (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1427                  (match_operand:SI 2 "low_register_operand" "l")))
1428    (clobber (reg:CC CC_REGNUM))]
1429   "TARGET_THUMB2 && optimize_size && reload_completed"
1430   "mul%!\\t%0, %2, %0"
1431   [(set_attr "predicable" "yes")
1432    (set_attr "length" "2")
1433    (set_attr "type" "muls")])
1435 (define_insn "*thumb2_mulsi_short_compare0"
1436   [(set (reg:CC_NZ CC_REGNUM)
1437         (compare:CC_NZ
1438          (mult:SI (match_operand:SI 1 "register_operand" "%0")
1439                   (match_operand:SI 2 "register_operand" "l"))
1440          (const_int 0)))
1441    (set (match_operand:SI 0 "register_operand" "=l")
1442         (mult:SI (match_dup 1) (match_dup 2)))]
1443   "TARGET_THUMB2 && optimize_size"
1444   "muls\\t%0, %2, %0"
1445   [(set_attr "length" "2")
1446    (set_attr "type" "muls")])
1448 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1449   [(set (reg:CC_NZ CC_REGNUM)
1450         (compare:CC_NZ
1451          (mult:SI (match_operand:SI 1 "register_operand" "%0")
1452                   (match_operand:SI 2 "register_operand" "l"))
1453          (const_int 0)))
1454    (clobber (match_scratch:SI 0 "=l"))]
1455   "TARGET_THUMB2 && optimize_size"
1456   "muls\\t%0, %2, %0"
1457   [(set_attr "length" "2")
1458    (set_attr "type" "muls")])
1460 (define_insn "*thumb2_cbz"
1461   [(set (pc) (if_then_else
1462               (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1463                   (const_int 0))
1464               (label_ref (match_operand 1 "" ""))
1465               (pc)))
1466    (clobber (reg:CC CC_REGNUM))]
1467   "TARGET_THUMB2"
1468   "*
1469   if (get_attr_length (insn) == 2)
1470     return \"cbz\\t%0, %l1\";
1471   else
1472     return \"cmp\\t%0, #0\;beq\\t%l1\";
1473   "
1474   [(set (attr "length")
1475         (if_then_else
1476             (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1477                  (le (minus (match_dup 1) (pc)) (const_int 128))
1478                  (not (match_test "which_alternative")))
1479             (const_int 2)
1480             (const_int 8)))
1481    (set_attr "type" "branch,multiple")]
1484 (define_insn "*thumb2_cbnz"
1485   [(set (pc) (if_then_else
1486               (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1487                   (const_int 0))
1488               (label_ref (match_operand 1 "" ""))
1489               (pc)))
1490    (clobber (reg:CC CC_REGNUM))]
1491   "TARGET_THUMB2"
1492   "*
1493   if (get_attr_length (insn) == 2)
1494     return \"cbnz\\t%0, %l1\";
1495   else
1496     return \"cmp\\t%0, #0\;bne\\t%l1\";
1497   "
1498   [(set (attr "length")
1499         (if_then_else
1500             (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1501                  (le (minus (match_dup 1) (pc)) (const_int 128))
1502                  (not (match_test "which_alternative")))
1503             (const_int 2)
1504             (const_int 8)))
1505    (set_attr "type" "branch,multiple")]
1508 (define_insn "*thumb2_one_cmplsi2_short"
1509   [(set (match_operand:SI 0 "low_register_operand" "=l")
1510         (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1511    (clobber (reg:CC CC_REGNUM))]
1512   "TARGET_THUMB2 && reload_completed"
1513   "mvn%!\t%0, %1"
1514   [(set_attr "predicable" "yes")
1515    (set_attr "length" "2")
1516    (set_attr "type" "mvn_reg")]
1519 (define_insn "*thumb2_negsi2_short"
1520   [(set (match_operand:SI 0 "low_register_operand" "=l")
1521         (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1522    (clobber (reg:CC CC_REGNUM))]
1523   "TARGET_THUMB2 && reload_completed"
1524   "rsb%!\t%0, %1, #0"
1525   [(set_attr "predicable" "yes")
1526    (set_attr "length" "2")
1527    (set_attr "type" "alu_sreg")]
1530 (define_insn "*orsi_notsi_si"
1531   [(set (match_operand:SI 0 "s_register_operand" "=r")
1532         (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1533                 (match_operand:SI 1 "s_register_operand" "r")))]
1534   "TARGET_THUMB2"
1535   "orn%?\\t%0, %1, %2"
1536   [(set_attr "predicable" "yes")
1537    (set_attr "type" "logic_reg")]
1540 (define_insn "*orsi_not_shiftsi_si"
1541   [(set (match_operand:SI 0 "s_register_operand" "=r")
1542         (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1543                          [(match_operand:SI 2 "s_register_operand" "r")
1544                           (match_operand:SI 3 "const_int_operand" "M")]))
1545                 (match_operand:SI 1 "s_register_operand" "r")))]
1546   "TARGET_THUMB2"
1547   "orn%?\\t%0, %1, %2%S4"
1548   [(set_attr "predicable" "yes")
1549    (set_attr "shift" "2")
1550    (set_attr "autodetect_type" "alu_shift_operator4")]
1553 (define_peephole2
1554   [(set (match_operand:CC_NZ 0 "cc_register" "")
1555         (compare:CC_NZ (zero_extract:SI
1556                           (match_operand:SI 1 "low_register_operand" "")
1557                           (const_int 1)
1558                           (match_operand:SI 2 "const_int_operand" ""))
1559                          (const_int 0)))
1560    (match_scratch:SI 3 "l")
1561    (set (pc)
1562         (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1563                        [(match_dup 0) (const_int 0)])
1564                       (match_operand 5 "" "")
1565                       (match_operand 6 "" "")))]
1566   "TARGET_THUMB2
1567    && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1568    && peep2_reg_dead_p (2, operands[0])"
1569   [(parallel [(set (match_dup 0)
1570                    (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1571                                     (const_int 0)))
1572               (clobber (match_dup 3))])
1573    (set (pc)
1574         (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1575                       (match_dup 5) (match_dup 6)))]
1576   "
1577   operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1578   operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1579                                 VOIDmode, operands[0], const0_rtx);
1580   ")
1582 (define_peephole2
1583   [(set (match_operand:CC_NZ 0 "cc_register" "")
1584         (compare:CC_NZ (zero_extract:SI
1585                           (match_operand:SI 1 "low_register_operand" "")
1586                           (match_operand:SI 2 "const_int_operand" "")
1587                           (const_int 0))
1588                          (const_int 0)))
1589    (match_scratch:SI 3 "l")
1590    (set (pc)
1591         (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1592                        [(match_dup 0) (const_int 0)])
1593                       (match_operand 5 "" "")
1594                       (match_operand 6 "" "")))]
1595   "TARGET_THUMB2
1596    && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1597    && peep2_reg_dead_p (2, operands[0])"
1598   [(parallel [(set (match_dup 0)
1599                    (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1600                                   (const_int 0)))
1601               (clobber (match_dup 3))])
1602    (set (pc)
1603         (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1604                       (match_dup 5) (match_dup 6)))]
1605   "
1606   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1607   ")
1609 ;; Define the subtract-one-and-jump insns so loop.c
1610 ;; knows what to generate.
1611 (define_expand "doloop_end"
1612   [(use (match_operand 0 "" ""))      ; loop pseudo
1613    (use (match_operand 1 "" ""))]     ; label
1614   "TARGET_32BIT"
1615   "
1617    /* Currently SMS relies on the do-loop pattern to recognize loops
1618       where (1) the control part consists of all insns defining and/or
1619       using a certain 'count' register and (2) the loop count can be
1620       adjusted by modifying this register prior to the loop.
1621       ??? The possible introduction of a new block to initialize the
1622       new IV can potentially affect branch optimizations.
1624       Also used to implement the low over head loops feature, which is part of
1625       the Armv8.1-M Mainline Low Overhead Branch (LOB) extension.  */
1626   if (optimize > 0 && (flag_modulo_sched || TARGET_HAVE_LOB))
1627     {
1628       rtx s0;
1629       rtx bcomp;
1630       rtx loc_ref;
1631       rtx cc_reg;
1632       rtx insn;
1633       rtx cmp;
1634       int decrement_num;
1636       if (GET_MODE (operands[0]) != SImode)
1637         FAIL;
1639       s0 = operands[0];
1641       if (TARGET_HAVE_LOB
1642           && arm_target_bb_ok_for_lob (BLOCK_FOR_INSN (operands[1])))
1643         {
1644           /* If we have a compatible MVE target, try and analyse the loop
1645              contents to determine if we can use predicated dlstp/letp
1646              looping.  These patterns implicitly use LR as the loop counter.  */
1647           if (TARGET_HAVE_MVE
1648               && ((decrement_num = arm_attempt_dlstp_transform (operands[1]))
1649                   != 1))
1650             {
1651               loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[1]);
1652               switch (decrement_num)
1653                 {
1654                   case 2:
1655                     insn = gen_predicated_doloop_end_internal2 (loc_ref);
1656                     break;
1657                   case 4:
1658                     insn = gen_predicated_doloop_end_internal4 (loc_ref);
1659                     break;
1660                   case 8:
1661                     insn = gen_predicated_doloop_end_internal8 (loc_ref);
1662                     break;
1663                   case 16:
1664                     insn = gen_predicated_doloop_end_internal16 (loc_ref);
1665                     break;
1666                   default:
1667                     gcc_unreachable ();
1668                 }
1669               emit_jump_insn (insn);
1670               DONE;
1671             }
1672           /* Remaining LOB cases need to explicitly use LR.  */
1673           s0 = gen_rtx_REG (SImode, LR_REGNUM);
1674         }
1676         /* Otherwise, try standard decrement-by-one dls/le looping.  */
1677         if (TARGET_THUMB2)
1678           insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0,
1679                                                         GEN_INT (-1)));
1680         else
1681           insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1683         cmp = XVECEXP (PATTERN (insn), 0, 0);
1684         cc_reg = SET_DEST (cmp);
1685         bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1686         loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[1]);
1687         emit_jump_insn (gen_rtx_SET (pc_rtx,
1688                                      gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1689                                                            loc_ref, pc_rtx)));
1690         DONE;
1691     }
1692   else
1693     FAIL;
1696 (define_insn "*clear_apsr"
1697   [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1698   (clobber (reg:CC CC_REGNUM))]
1699   "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1700   "clrm%?\\t{APSR}"
1701   [(set_attr "predicable" "yes")]
1704 ;; The operands are validated through the clear_multiple_operation
1705 ;; match_parallel predicate rather than through constraints so enable it only
1706 ;; after reload.
1707 (define_insn "*clear_multiple"
1708   [(match_parallel 0 "clear_multiple_operation"
1709      [(set (match_operand:SI 1 "register_operand" "")
1710            (const_int 0))])]
1711   "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1712   {
1713     char pattern[100];
1714     int i, num_saves = XVECLEN (operands[0], 0);
1716     strcpy (pattern, \"clrm%?\\t{\");
1717     for (i = 0; i < num_saves; i++)
1718       {
1719         if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1720           {
1721             strcat (pattern, \"APSR\");
1722             ++i;
1723           }
1724         else
1725           strcat (pattern,
1726                   reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1727         if (i < num_saves - 1)
1728           strcat (pattern, \", %|\");
1729       }
1730     strcat (pattern, \"}\");
1731     output_asm_insn (pattern, operands);
1732     return \"\";
1733   }
1734   [(set_attr "predicable" "yes")]
1737 (define_insn "thumb2_asrl"
1738   [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1739         (ashiftrt:DI (match_dup 0)
1740                      (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1741   "TARGET_HAVE_MVE"
1742   "asrl%?\\t%Q0, %R0, %1"
1743   [(set_attr "predicable" "yes")])
1745 (define_insn "thumb2_lsll"
1746   [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1747         (ashift:DI (match_dup 0)
1748                    (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1749   "TARGET_HAVE_MVE"
1750   "lsll%?\\t%Q0, %R0, %1"
1751   [(set_attr "predicable" "yes")])
1753 (define_insn "thumb2_lsrl"
1754   [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1755         (lshiftrt:DI (match_dup 0)
1756                      (match_operand:SI 1 "long_shift_imm" "Pg")))]
1757   "TARGET_HAVE_MVE"
1758   "lsrl%?\\t%Q0, %R0, %1"
1759   [(set_attr "predicable" "yes")])
1761 ;; Originally expanded by 'doloop_end'.
1762 (define_insn "*doloop_end_internal"
1763   [(set (pc)
1764         (if_then_else
1765             (ne (reg:SI LR_REGNUM) (const_int 1))
1766           (label_ref (match_operand 0 "" ""))
1767           (pc)))
1768    (set (reg:SI LR_REGNUM)
1769         (plus:SI (reg:SI LR_REGNUM) (const_int -1)))
1770    (clobber (reg:CC CC_REGNUM))]
1771   "TARGET_32BIT && TARGET_HAVE_LOB"
1772   {
1773     if (get_attr_length (insn) == 4)
1774       return "le\t%|lr, %l0";
1775     else
1776       return "subs\t%|lr, #1;bne\t%l0";
1777   }
1778   [(set (attr "length")
1779         (if_then_else
1780             (ltu (minus (pc) (match_dup 0)) (const_int 1024))
1781             (const_int 4)
1782             (const_int 6)))
1783    (set_attr "type" "branch")])
1785 (define_expand "doloop_begin"
1786   [(match_operand 0 "" "")
1787    (match_operand 1 "" "")]
1788   "TARGET_32BIT && TARGET_HAVE_LOB"
1789   {
1790     if (REGNO (operands[0]) == LR_REGNUM)
1791       {
1792         /* Pick out the number by which we are decrementing the loop counter
1793            in every iteration.  If it's > 1, then use dlstp.  */
1794         int const_int_dec_num
1795              = abs (INTVAL (XEXP (XEXP (XVECEXP (PATTERN (operands[1]), 0, 1),
1796                                   1),
1797                             1)));
1798         switch (const_int_dec_num)
1799           {
1800             case 16:
1801               emit_insn (gen_dlstp8_insn (operands[0]));
1802               break;
1804             case 8:
1805               emit_insn (gen_dlstp16_insn (operands[0]));
1806               break;
1808             case 4:
1809               emit_insn (gen_dlstp32_insn (operands[0]));
1810               break;
1812             case 2:
1813               emit_insn (gen_dlstp64_insn (operands[0]));
1814               break;
1816             case 1:
1817               emit_insn (gen_dls_insn (operands[0]));
1818               break;
1820             default:
1821               gcc_unreachable ();
1822           }
1823         DONE;
1824       }
1825     else
1826       FAIL;
1827   })
1829 (define_insn "dls_insn"
1830   [(set (reg:SI LR_REGNUM)
1831         (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))]
1832   "TARGET_32BIT && TARGET_HAVE_LOB"
1833   "dls\t%|lr, %0")