1;; ARM Thumb-2 Machine Description
2;; Copyright (C) 2007-2022 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.
11;;
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.
16;;
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/>.  */
20
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.
26
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")]
48)
49
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")]
69)
70
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")]
90)
91
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")]
111)
112
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);
128
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")]
164)
165
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);
181
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")]
217)
218
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")]
228)
229
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))"
241{
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    }
258}
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,*")]
265)
266
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")]
282)
283
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")]
305)
306
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")]
320)
321
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")]
338)
339
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")]
359)
360
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]);
379
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);
385
386  }
387  [(set_attr "conds" "use")
388   (set_attr "length" "8")
389   (set_attr "type" "multiple")]
390)
391
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")]
410)
411
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")]
433)
434
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;
468
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);
478
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")])]
512)
513
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")]
527)
528
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")]
537)
538
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")]
549)
550
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")]
561)
562
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")]
572)
573
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")]
586)
587
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")]
599)
600
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")]
608)
609;; Don't define thumb2_load_indirect_jump because we can't guarantee label
610;; addresses will have the thumb bit set correctly.
611
612
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]);
627
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)))]
639)
640
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]);
659
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")]
670)
671
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]);
686
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")]
696)
697
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")]
746)
747
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\";
760
761    output_asm_insn (\"cmp\\t%2, %3\", operands);
762
763    if (GET_CODE (operands[5]) == PLUS && TARGET_COND_ARITH)
764      return \"cinc\\t%0, %1, %d4\";
765
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")]
788)
789
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;
808
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      }
822
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])));
827
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")]
859)
860
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")]
891)
892
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);
905
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]));
924
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);
939
940       emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
941                                                                      operands[2])));
942
943       emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
944
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")]
958)
959
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")]
972)
973
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")]
987)
988
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")]
1001)
1002
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    }
1032
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")]
1085)
1086
1087;; Zero and sign extension instructions.
1088
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")]
1102)
1103
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")]
1115)
1116
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")]
1128)
1129
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"
1141{
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;
1148})
1149
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")]
1166)
1167
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"
1180{
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;
1187})
1188
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")]
1206)
1207
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")]
1214)
1215
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")]
1233)
1234
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  }"
1248)
1249
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")]
1263)
1264
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")))]
1283)
1284
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")]
1294)
1295
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;
1304
1305    if (CONST_INT_P (operands[2]))
1306      val = INTVAL(operands[2]);
1307    else
1308      val = 0;
1309
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")])]
1323)
1324
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")]
1335)
1336
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]));"
1348)
1349
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]));"
1361)
1362
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;
1374
1375    if (CONST_INT_P (operands[2]))
1376      val = INTVAL (operands[2]);
1377    else
1378      val = 0;
1379
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"))])]
1395)
1396
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;
1406
1407    if (CONST_INT_P (operands[1]))
1408      val = INTVAL (operands[1]);
1409    else
1410      val = 0;
1411
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")))]
1422)
1423
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")])
1434
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")])
1447
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")])
1459
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")]
1482)
1483
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")]
1506)
1507
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")]
1517)
1518
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")]
1528)
1529
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")]
1538)
1539
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")]
1551)
1552
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  ")
1581
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  ")
1608
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  "
1616 {
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.
1623
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
1635     if (GET_MODE (operands[0]) != SImode)
1636       FAIL;
1637
1638     s0 = operands [0];
1639
1640     /* Low over head loop instructions require the first operand to be LR.  */
1641     if (TARGET_HAVE_LOB && arm_target_insn_ok_for_lob (operands [1]))
1642       s0 = gen_rtx_REG (SImode, LR_REGNUM);
1643
1644     if (TARGET_THUMB2)
1645       insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1646     else
1647       insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1648
1649     cmp = XVECEXP (PATTERN (insn), 0, 0);
1650     cc_reg = SET_DEST (cmp);
1651     bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1652     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1653     emit_jump_insn (gen_rtx_SET (pc_rtx,
1654                                  gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1655                                                        loc_ref, pc_rtx)));
1656     DONE;
1657   }
1658 else
1659   FAIL;
1660 }")
1661
1662(define_insn "*clear_apsr"
1663  [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1664  (clobber (reg:CC CC_REGNUM))]
1665  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1666  "clrm%?\\t{APSR}"
1667  [(set_attr "predicable" "yes")]
1668)
1669
1670;; The operands are validated through the clear_multiple_operation
1671;; match_parallel predicate rather than through constraints so enable it only
1672;; after reload.
1673(define_insn "*clear_multiple"
1674  [(match_parallel 0 "clear_multiple_operation"
1675     [(set (match_operand:SI 1 "register_operand" "")
1676             (const_int 0))])]
1677  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1678  {
1679    char pattern[100];
1680    int i, num_saves = XVECLEN (operands[0], 0);
1681
1682    strcpy (pattern, \"clrm%?\\t{\");
1683    for (i = 0; i < num_saves; i++)
1684      {
1685          if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1686            {
1687              strcat (pattern, \"APSR\");
1688              ++i;
1689            }
1690          else
1691            strcat (pattern,
1692                      reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1693          if (i < num_saves - 1)
1694            strcat (pattern, \", %|\");
1695      }
1696    strcat (pattern, \"}\");
1697    output_asm_insn (pattern, operands);
1698    return \"\";
1699  }
1700  [(set_attr "predicable" "yes")]
1701)
1702
1703(define_insn "thumb2_asrl"
1704  [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1705          (ashiftrt:DI (match_dup 0)
1706                         (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1707  "TARGET_HAVE_MVE"
1708  "asrl%?\\t%Q0, %R0, %1"
1709  [(set_attr "predicable" "yes")])
1710
1711(define_insn "thumb2_lsll"
1712  [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1713          (ashift:DI (match_dup 0)
1714                       (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1715  "TARGET_HAVE_MVE"
1716  "lsll%?\\t%Q0, %R0, %1"
1717  [(set_attr "predicable" "yes")])
1718
1719(define_insn "thumb2_lsrl"
1720  [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1721          (lshiftrt:DI (match_dup 0)
1722                         (match_operand:SI 1 "long_shift_imm" "Pg")))]
1723  "TARGET_HAVE_MVE"
1724  "lsrl%?\\t%Q0, %R0, %1"
1725  [(set_attr "predicable" "yes")])
1726
1727;; Originally expanded by 'doloop_end'.
1728(define_insn "*doloop_end_internal"
1729  [(set (pc)
1730        (if_then_else
1731            (ne (reg:SI LR_REGNUM) (const_int 1))
1732          (label_ref (match_operand 0 "" ""))
1733          (pc)))
1734   (set (reg:SI LR_REGNUM)
1735        (plus:SI (reg:SI LR_REGNUM) (const_int -1)))
1736   (clobber (reg:CC CC_REGNUM))]
1737  "TARGET_32BIT && TARGET_HAVE_LOB"
1738  {
1739    if (get_attr_length (insn) == 4)
1740      return "le\t%|lr, %l0";
1741    else
1742      return "subs\t%|lr, #1;bne\t%l0";
1743  }
1744  [(set (attr "length")
1745        (if_then_else
1746            (ltu (minus (pc) (match_dup 0)) (const_int 1024))
1747              (const_int 4)
1748              (const_int 6)))
1749   (set_attr "type" "branch")])
1750
1751(define_expand "doloop_begin"
1752  [(match_operand 0 "" "")
1753   (match_operand 1 "" "")]
1754  "TARGET_32BIT && TARGET_HAVE_LOB"
1755  {
1756    if (REGNO (operands[0]) == LR_REGNUM)
1757      {
1758          emit_insn (gen_dls_insn (operands[0]));
1759          DONE;
1760      }
1761    else
1762      FAIL;
1763  })
1764
1765(define_insn "dls_insn"
1766  [(set (reg:SI LR_REGNUM)
1767        (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))]
1768  "TARGET_32BIT && TARGET_HAVE_LOB"
1769  "dls\t%|lr, %0")
1770