1;; ARM Thumb-2 Machine Description
2;; Copyright (C) 2007-2020 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    if (GET_CODE (operands[5]) == AND)
763      {
764	output_asm_insn (\"ite\\t%D4\", operands);
765	output_asm_insn (\"mov%D4\\t%0, #0\", operands);
766      }
767    else if (GET_CODE (operands[5]) == MINUS)
768      {
769	output_asm_insn (\"ite\\t%D4\", operands);
770	output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
771      }
772    else if (which_alternative != 0)
773      {
774	output_asm_insn (\"ite\\t%D4\", operands);
775	output_asm_insn (\"mov%D4\\t%0, %1\", operands);
776      }
777    else
778      output_asm_insn (\"it\\t%d4\", operands);
779    return \"%i5%d4\\t%0, %1, #1\";
780  "
781  [(set_attr "conds" "clob")
782   (set_attr "length" "14")
783   (set_attr "type" "multiple")]
784)
785
786(define_insn_and_split "*thumb2_cond_arith_strict_it"
787  [(set (match_operand:SI 0 "s_register_operand" "=l")
788        (match_operator:SI 5 "shiftable_operator_strict_it"
789	 [(match_operator:SI 4 "arm_comparison_operator"
790           [(match_operand:SI 2 "s_register_operand" "r")
791	    (match_operand:SI 3 "arm_rhs_operand" "rI")])
792          (match_operand:SI 1 "s_register_operand" "0")]))
793   (clobber (reg:CC CC_REGNUM))]
794  "TARGET_THUMB2 && arm_restrict_it"
795  "#"
796  "&& reload_completed"
797  [(const_int 0)]
798  {
799    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
800      {
801        /*  %i5 %0, %1, %2, lsr #31  */
802        rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
803        rtx op = NULL_RTX;
804
805        switch (GET_CODE (operands[5]))
806          {
807          case AND:
808            op = gen_rtx_AND (SImode, shifted_op, operands[1]);
809            break;
810           case PLUS:
811            op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
812            break;
813          default: gcc_unreachable ();
814          }
815        emit_insn (gen_rtx_SET (operands[0], op));
816        DONE;
817      }
818
819    /*  "cmp  %2, %3"  */
820    emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
821                            gen_rtx_COMPARE (CCmode, operands[2],
822					     operands[3])));
823
824    if (GET_CODE (operands[5]) == AND)
825      {
826        /*  %i5  %0, %1, #1
827            it%D4
828            mov%D4  %0, #0  */
829        enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
830        emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
831							  GEN_INT (1))));
832        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
833                                      gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
834                                      gen_rtx_SET (operands[0], const0_rtx)));
835        DONE;
836      }
837    else
838      {
839        /*  it\\t%d4
840            %i5%d4\\t%0, %1, #1   */
841        emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
842                                                                VOIDmode,
843                                                                gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
844                                                gen_rtx_SET (operands[0],
845                                                            gen_rtx_PLUS (SImode,
846                                                                          operands[1],
847                                                                          GEN_INT (1)))));
848        DONE;
849      }
850     FAIL;
851  }
852  [(set_attr "conds" "clob")
853   (set_attr "length" "12")
854   (set_attr "type" "multiple")]
855)
856
857(define_insn "*thumb2_cond_sub"
858  [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
859        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
860		  (match_operator:SI 4 "arm_comparison_operator"
861                   [(match_operand:SI 2 "s_register_operand" "r,r")
862		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
863   (clobber (reg:CC CC_REGNUM))]
864  "TARGET_THUMB2"
865  "*
866    output_asm_insn (\"cmp\\t%2, %3\", operands);
867    if (which_alternative != 0)
868      {
869	if (arm_restrict_it)
870	  {
871	    output_asm_insn (\"mov\\t%0, %1\", operands);
872	    output_asm_insn (\"it\\t%d4\", operands);
873	  }
874	else
875	{
876	  output_asm_insn (\"ite\\t%D4\", operands);
877	  output_asm_insn (\"mov%D4\\t%0, %1\", operands);
878	}
879      }
880    else
881      output_asm_insn (\"it\\t%d4\", operands);
882    return \"sub%d4\\t%0, %1, #1\";
883  "
884  [(set_attr "conds" "clob")
885   (set_attr "length" "10,14")
886   (set_attr "type" "multiple")]
887)
888
889(define_insn_and_split "*thumb2_negscc"
890  [(set (match_operand:SI 0 "s_register_operand" "=Ts")
891	(neg:SI (match_operator 3 "arm_comparison_operator"
892		 [(match_operand:SI 1 "s_register_operand" "r")
893		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
894   (clobber (reg:CC CC_REGNUM))]
895  "TARGET_THUMB2"
896  "#"
897  "&& reload_completed"
898  [(const_int 0)]
899  {
900    rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
901
902    if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
903      {
904        /* Emit asr\\t%0, %1, #31 */
905        emit_insn (gen_rtx_SET (operands[0],
906                                gen_rtx_ASHIFTRT (SImode,
907                                                  operands[1],
908                                                  GEN_INT (31))));
909        DONE;
910      }
911    else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
912      {
913        /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
914        if (CONST_INT_P (operands[2]))
915          emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
916                                        gen_int_mode (-INTVAL (operands[2]),
917						      SImode)));
918        else
919          emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
920
921        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
922                                      gen_rtx_NE (SImode,
923                                                  cc_reg,
924                                                  const0_rtx),
925                                      gen_rtx_SET (operands[0],
926                                                   GEN_INT (~0))));
927        DONE;
928      }
929    else
930      {
931       /* Emit:  cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
932       enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
933       machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
934       rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
935
936       emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
937							operands[2])));
938
939       emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
940
941       emit_insn (gen_rtx_COND_EXEC (VOIDmode,
942                                     gen_rtx_fmt_ee (rc,
943                                                     VOIDmode,
944                                                     tmp1,
945                                                     const0_rtx),
946                                     gen_rtx_SET (operands[0], const0_rtx)));
947       DONE;
948      }
949    FAIL;
950  }
951  [(set_attr "conds" "clob")
952   (set_attr "length" "14")
953   (set_attr "type" "multiple")]
954)
955
956(define_insn "*thumb2_movcond"
957  [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
958	(if_then_else:SI
959	 (match_operator 5 "arm_comparison_operator"
960	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
961	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
962	 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
963	 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
964   (clobber (reg:CC CC_REGNUM))]
965  "TARGET_THUMB2"
966  "*
967  if (GET_CODE (operands[5]) == LT
968      && (operands[4] == const0_rtx))
969    {
970      if (which_alternative != 1 && REG_P (operands[1]))
971	{
972	  if (operands[2] == const0_rtx)
973	    return \"and\\t%0, %1, %3, asr #31\";
974	  return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
975	}
976      else if (which_alternative != 0 && REG_P (operands[2]))
977	{
978	  if (operands[1] == const0_rtx)
979	    return \"bic\\t%0, %2, %3, asr #31\";
980	  return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
981	}
982      /* The only case that falls through to here is when both ops 1 & 2
983	 are constants.  */
984    }
985
986  if (GET_CODE (operands[5]) == GE
987      && (operands[4] == const0_rtx))
988    {
989      if (which_alternative != 1 && REG_P (operands[1]))
990	{
991	  if (operands[2] == const0_rtx)
992	    return \"bic\\t%0, %1, %3, asr #31\";
993	  return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
994	}
995      else if (which_alternative != 0 && REG_P (operands[2]))
996	{
997	  if (operands[1] == const0_rtx)
998	    return \"and\\t%0, %2, %3, asr #31\";
999	  return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
1000	}
1001      /* The only case that falls through to here is when both ops 1 & 2
1002	 are constants.  */
1003    }
1004  if (CONST_INT_P (operands[4])
1005      && !const_ok_for_arm (INTVAL (operands[4])))
1006    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
1007  else
1008    output_asm_insn (\"cmp\\t%3, %4\", operands);
1009  switch (which_alternative)
1010    {
1011    case 0:
1012      output_asm_insn (\"it\\t%D5\", operands);
1013      break;
1014    case 1:
1015      output_asm_insn (\"it\\t%d5\", operands);
1016      break;
1017    case 2:
1018      if (arm_restrict_it)
1019        {
1020          output_asm_insn (\"mov\\t%0, %1\", operands);
1021          output_asm_insn (\"it\\t%D5\", operands);
1022        }
1023      else
1024        output_asm_insn (\"ite\\t%d5\", operands);
1025      break;
1026    default:
1027      abort();
1028    }
1029  if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1030    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1031  if (which_alternative != 1)
1032    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1033  return \"\";
1034  "
1035  [(set_attr "conds" "clob")
1036   (set_attr "length" "10,10,14")
1037   (set_attr "type" "multiple")]
1038)
1039
1040;; Zero and sign extension instructions.
1041
1042;; All supported Thumb2 implementations are armv6, so only that case is
1043;; provided.
1044(define_insn "*thumb2_extendqisi_v6"
1045  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1046	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1047  "TARGET_THUMB2 && arm_arch6"
1048  "@
1049   sxtb%?\\t%0, %1
1050   ldrsb%?\\t%0, %1"
1051  [(set_attr "type" "extend,load_byte")
1052   (set_attr "predicable" "yes")
1053   (set_attr "pool_range" "*,4094")
1054   (set_attr "neg_pool_range" "*,250")]
1055)
1056
1057(define_insn "*thumb2_zero_extendhisi2_v6"
1058  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1059	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1060  "TARGET_THUMB2 && arm_arch6"
1061  "@
1062   uxth%?\\t%0, %1
1063   ldrh%?\\t%0, %1"
1064  [(set_attr "type" "extend,load_byte")
1065   (set_attr "predicable" "yes")
1066   (set_attr "pool_range" "*,4094")
1067   (set_attr "neg_pool_range" "*,250")]
1068)
1069
1070(define_insn "thumb2_zero_extendqisi2_v6"
1071  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1072	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1073  "TARGET_THUMB2 && arm_arch6"
1074  "@
1075   uxtb%?\\t%0, %1
1076   ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1077  [(set_attr "type" "extend,load_byte")
1078   (set_attr "predicable" "yes")
1079   (set_attr "pool_range" "*,4094")
1080   (set_attr "neg_pool_range" "*,250")]
1081)
1082
1083(define_expand "thumb2_casesi_internal"
1084  [(parallel [(set (pc)
1085	       (if_then_else
1086		(leu (match_operand:SI 0 "s_register_operand")
1087		     (match_operand:SI 1 "arm_rhs_operand"))
1088		(match_dup 4)
1089		(label_ref:SI (match_operand 3 ""))))
1090	      (clobber (reg:CC CC_REGNUM))
1091	      (clobber (match_scratch:SI 5))
1092	      (use (label_ref:SI (match_operand 2 "")))])]
1093  "TARGET_THUMB2 && !flag_pic"
1094{
1095  operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1096  operands[4] = gen_rtx_PLUS (SImode, operands[4],
1097			      gen_rtx_LABEL_REF (SImode, operands[2]));
1098  operands[4] = gen_rtx_MEM (SImode, operands[4]);
1099  MEM_READONLY_P (operands[4]) = 1;
1100  MEM_NOTRAP_P (operands[4]) = 1;
1101})
1102
1103(define_insn "*thumb2_casesi_internal"
1104  [(parallel [(set (pc)
1105	       (if_then_else
1106		(leu (match_operand:SI 0 "s_register_operand" "r")
1107		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
1108		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1109				 (label_ref:SI (match_operand 2 "" ""))))
1110		(label_ref:SI (match_operand 3 "" ""))))
1111	      (clobber (reg:CC CC_REGNUM))
1112	      (clobber (match_scratch:SI 4 "=&r"))
1113	      (use (label_ref:SI (match_dup 2)))])]
1114  "TARGET_THUMB2 && !flag_pic"
1115  "* return thumb2_output_casesi(operands);"
1116  [(set_attr "conds" "clob")
1117   (set_attr "length" "16")
1118   (set_attr "type" "multiple")]
1119)
1120
1121(define_expand "thumb2_casesi_internal_pic"
1122  [(parallel [(set (pc)
1123	       (if_then_else
1124		(leu (match_operand:SI 0 "s_register_operand")
1125		     (match_operand:SI 1 "arm_rhs_operand"))
1126		(match_dup 4)
1127		(label_ref:SI (match_operand 3 ""))))
1128	      (clobber (reg:CC CC_REGNUM))
1129	      (clobber (match_scratch:SI 5))
1130	      (clobber (match_scratch:SI 6))
1131	      (use (label_ref:SI (match_operand 2 "")))])]
1132  "TARGET_THUMB2 && flag_pic"
1133{
1134  operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1135  operands[4] = gen_rtx_PLUS (SImode, operands[4],
1136			      gen_rtx_LABEL_REF (SImode, operands[2]));
1137  operands[4] = gen_rtx_MEM (SImode, operands[4]);
1138  MEM_READONLY_P (operands[4]) = 1;
1139  MEM_NOTRAP_P (operands[4]) = 1;
1140})
1141
1142(define_insn "*thumb2_casesi_internal_pic"
1143  [(parallel [(set (pc)
1144	       (if_then_else
1145		(leu (match_operand:SI 0 "s_register_operand" "r")
1146		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
1147		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1148				 (label_ref:SI (match_operand 2 "" ""))))
1149		(label_ref:SI (match_operand 3 "" ""))))
1150	      (clobber (reg:CC CC_REGNUM))
1151	      (clobber (match_scratch:SI 4 "=&r"))
1152	      (clobber (match_scratch:SI 5 "=r"))
1153	      (use (label_ref:SI (match_dup 2)))])]
1154  "TARGET_THUMB2 && flag_pic"
1155  "* return thumb2_output_casesi(operands);"
1156  [(set_attr "conds" "clob")
1157   (set_attr "length" "20")
1158   (set_attr "type" "multiple")]
1159)
1160
1161(define_insn "*thumb2_return"
1162  [(simple_return)]
1163  "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1164  "* return output_return_instruction (const_true_rtx, true, false, true);"
1165  [(set_attr "type" "branch")
1166   (set_attr "length" "4")]
1167)
1168
1169(define_insn "*thumb2_cmse_entry_return"
1170  [(simple_return)]
1171  "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1172  "* return output_return_instruction (const_true_rtx, true, false, true);"
1173  [(set_attr "type" "branch")
1174   ; This is a return from a cmse_nonsecure_entry function so code will be
1175   ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1176   ; we adapt the length accordingly.
1177   (set (attr "length")
1178     (if_then_else (match_test "TARGET_HARD_FLOAT")
1179      (const_int 34)
1180      (const_int 8)))
1181   ; We do not support predicate execution of returns from cmse_nonsecure_entry
1182   ; functions because we need to clear the APSR.  Since predicable has to be
1183   ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1184   ; functions.
1185   (set_attr "predicable" "no")]
1186)
1187
1188(define_insn_and_split "thumb2_eh_return"
1189  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1190		    VUNSPEC_EH_RETURN)
1191   (clobber (match_scratch:SI 1 "=&r"))]
1192  "TARGET_THUMB2"
1193  "#"
1194  "&& reload_completed"
1195  [(const_int 0)]
1196  "
1197  {
1198    thumb_set_return_address (operands[0], operands[1]);
1199    DONE;
1200  }"
1201)
1202
1203(define_insn "*thumb2_alusi3_short"
1204  [(set (match_operand:SI          0 "s_register_operand" "=l")
1205        (match_operator:SI 3 "thumb_16bit_operator"
1206	 [(match_operand:SI 1 "s_register_operand" "0")
1207	  (match_operand:SI 2 "s_register_operand" "l")]))
1208   (clobber (reg:CC CC_REGNUM))]
1209  "TARGET_THUMB2 && reload_completed
1210   && GET_CODE(operands[3]) != PLUS
1211   && GET_CODE(operands[3]) != MINUS"
1212  "%I3%!\\t%0, %1, %2"
1213  [(set_attr "predicable" "yes")
1214   (set_attr "length" "2")
1215   (set_attr "type" "alu_sreg")]
1216)
1217
1218(define_insn "*thumb2_shiftsi3_short"
1219  [(set (match_operand:SI   0 "low_register_operand" "=l,l")
1220	(match_operator:SI  3 "shift_operator"
1221	 [(match_operand:SI 1 "low_register_operand"  "0,l")
1222	  (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1223   (clobber (reg:CC CC_REGNUM))]
1224  "TARGET_THUMB2 && reload_completed
1225   && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1226       || REG_P (operands[2]))"
1227  "* return arm_output_shift(operands, 2);"
1228  [(set_attr "predicable" "yes")
1229   (set_attr "shift" "1")
1230   (set_attr "length" "2")
1231   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1232		      (const_string "alu_shift_imm")
1233		      (const_string "alu_shift_reg")))]
1234)
1235
1236(define_insn "*thumb2_mov<mode>_shortim"
1237  [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1238	(match_operand:QHSI 1 "const_int_operand" "I"))
1239   (clobber (reg:CC CC_REGNUM))]
1240  "TARGET_THUMB2 && reload_completed"
1241  "mov%!\t%0, %1"
1242  [(set_attr "predicable" "yes")
1243   (set_attr "length" "2")
1244   (set_attr "type" "mov_imm")]
1245)
1246
1247(define_insn "*thumb2_addsi_short"
1248  [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1249	(plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1250		 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1251   (clobber (reg:CC CC_REGNUM))]
1252  "TARGET_THUMB2 && reload_completed"
1253  "*
1254    HOST_WIDE_INT val;
1255
1256    if (CONST_INT_P (operands[2]))
1257      val = INTVAL(operands[2]);
1258    else
1259      val = 0;
1260
1261    /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff.  */
1262    if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1263      return \"sub%!\\t%0, %1, #%n2\";
1264    else
1265      return \"add%!\\t%0, %1, %2\";
1266  "
1267  [(set_attr "predicable" "yes")
1268   (set_attr "length" "2")
1269   (set_attr_alternative "type"
1270                         [(if_then_else (match_operand 2 "const_int_operand" "")
1271                                        (const_string "alu_imm")
1272                                        (const_string "alu_sreg"))
1273                          (const_string "alu_imm")])]
1274)
1275
1276(define_insn "*thumb2_subsi_short"
1277  [(set (match_operand:SI 0 "low_register_operand" "=l")
1278	(minus:SI (match_operand:SI 1 "low_register_operand" "l")
1279		  (match_operand:SI 2 "low_register_operand" "l")))
1280   (clobber (reg:CC CC_REGNUM))]
1281  "TARGET_THUMB2 && reload_completed"
1282  "sub%!\\t%0, %1, %2"
1283  [(set_attr "predicable" "yes")
1284   (set_attr "length" "2")
1285   (set_attr "type" "alu_sreg")]
1286)
1287
1288(define_peephole2
1289  [(set (match_operand:CC 0 "cc_register" "")
1290	(compare:CC (match_operand:SI 1 "low_register_operand" "")
1291		    (match_operand:SI 2 "const_int_operand" "")))]
1292  "TARGET_THUMB2
1293   && peep2_reg_dead_p (1, operands[1])
1294   && satisfies_constraint_Pw (operands[2])"
1295  [(parallel
1296    [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1297     (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1298  "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1299)
1300
1301(define_peephole2
1302  [(match_scratch:SI 3 "l")
1303   (set (match_operand:CC 0 "cc_register" "")
1304	(compare:CC (match_operand:SI 1 "low_register_operand" "")
1305		    (match_operand:SI 2 "const_int_operand" "")))]
1306  "TARGET_THUMB2
1307   && satisfies_constraint_Px (operands[2])"
1308  [(parallel
1309    [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1310     (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1311  "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1312)
1313
1314(define_insn "thumb2_addsi3_compare0"
1315  [(set (reg:CC_NZ CC_REGNUM)
1316	(compare:CC_NZ
1317	  (plus:SI (match_operand:SI 1 "s_register_operand" "l,  0, r")
1318		   (match_operand:SI 2 "arm_add_operand"    "lPt,Ps,rIL"))
1319	  (const_int 0)))
1320   (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1321	(plus:SI (match_dup 1) (match_dup 2)))]
1322  "TARGET_THUMB2"
1323  "*
1324    HOST_WIDE_INT val;
1325
1326    if (CONST_INT_P (operands[2]))
1327      val = INTVAL (operands[2]);
1328    else
1329      val = 0;
1330
1331    if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1332      return \"subs\\t%0, %1, #%n2\";
1333    else
1334      return \"adds\\t%0, %1, %2\";
1335  "
1336  [(set_attr "conds" "set")
1337   (set_attr "length" "2,2,4")
1338   (set_attr_alternative "type"
1339                         [(if_then_else (match_operand 2 "const_int_operand" "")
1340                                        (const_string "alus_imm")
1341                                        (const_string "alus_sreg"))
1342                          (const_string "alus_imm")
1343                          (if_then_else (match_operand 2 "const_int_operand" "")
1344                                        (const_string "alus_imm")
1345                                        (const_string "alus_sreg"))])]
1346)
1347
1348(define_insn "*thumb2_addsi3_compare0_scratch"
1349  [(set (reg:CC_NZ CC_REGNUM)
1350	(compare:CC_NZ
1351	  (plus:SI (match_operand:SI 0 "s_register_operand" "l,  r")
1352		   (match_operand:SI 1 "arm_add_operand"    "lPv,rIL"))
1353	  (const_int 0)))]
1354  "TARGET_THUMB2"
1355  "*
1356    HOST_WIDE_INT val;
1357
1358    if (CONST_INT_P (operands[1]))
1359      val = INTVAL (operands[1]);
1360    else
1361      val = 0;
1362
1363    if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1364      return \"cmp\\t%0, #%n1\";
1365    else
1366      return \"cmn\\t%0, %1\";
1367  "
1368  [(set_attr "conds" "set")
1369   (set_attr "length" "2,4")
1370   (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1371                                    (const_string "alus_imm")
1372                                    (const_string "alus_sreg")))]
1373)
1374
1375(define_insn "*thumb2_mulsi_short"
1376  [(set (match_operand:SI 0 "low_register_operand" "=l")
1377        (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1378                 (match_operand:SI 2 "low_register_operand" "l")))
1379   (clobber (reg:CC CC_REGNUM))]
1380  "TARGET_THUMB2 && optimize_size && reload_completed"
1381  "mul%!\\t%0, %2, %0"
1382  [(set_attr "predicable" "yes")
1383   (set_attr "length" "2")
1384   (set_attr "type" "muls")])
1385
1386(define_insn "*thumb2_mulsi_short_compare0"
1387  [(set (reg:CC_NZ CC_REGNUM)
1388        (compare:CC_NZ
1389         (mult:SI (match_operand:SI 1 "register_operand" "%0")
1390	          (match_operand:SI 2 "register_operand" "l"))
1391         (const_int 0)))
1392   (set (match_operand:SI 0 "register_operand" "=l")
1393	(mult:SI (match_dup 1) (match_dup 2)))]
1394  "TARGET_THUMB2 && optimize_size"
1395  "muls\\t%0, %2, %0"
1396  [(set_attr "length" "2")
1397   (set_attr "type" "muls")])
1398
1399(define_insn "*thumb2_mulsi_short_compare0_scratch"
1400  [(set (reg:CC_NZ CC_REGNUM)
1401        (compare:CC_NZ
1402         (mult:SI (match_operand:SI 1 "register_operand" "%0")
1403	          (match_operand:SI 2 "register_operand" "l"))
1404         (const_int 0)))
1405   (clobber (match_scratch:SI 0 "=l"))]
1406  "TARGET_THUMB2 && optimize_size"
1407  "muls\\t%0, %2, %0"
1408  [(set_attr "length" "2")
1409   (set_attr "type" "muls")])
1410
1411(define_insn "*thumb2_cbz"
1412  [(set (pc) (if_then_else
1413	      (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1414		  (const_int 0))
1415	      (label_ref (match_operand 1 "" ""))
1416	      (pc)))
1417   (clobber (reg:CC CC_REGNUM))]
1418  "TARGET_THUMB2"
1419  "*
1420  if (get_attr_length (insn) == 2)
1421    return \"cbz\\t%0, %l1\";
1422  else
1423    return \"cmp\\t%0, #0\;beq\\t%l1\";
1424  "
1425  [(set (attr "length")
1426        (if_then_else
1427	    (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1428	         (le (minus (match_dup 1) (pc)) (const_int 128))
1429	         (not (match_test "which_alternative")))
1430	    (const_int 2)
1431	    (const_int 8)))
1432   (set_attr "type" "branch,multiple")]
1433)
1434
1435(define_insn "*thumb2_cbnz"
1436  [(set (pc) (if_then_else
1437	      (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1438		  (const_int 0))
1439	      (label_ref (match_operand 1 "" ""))
1440	      (pc)))
1441   (clobber (reg:CC CC_REGNUM))]
1442  "TARGET_THUMB2"
1443  "*
1444  if (get_attr_length (insn) == 2)
1445    return \"cbnz\\t%0, %l1\";
1446  else
1447    return \"cmp\\t%0, #0\;bne\\t%l1\";
1448  "
1449  [(set (attr "length")
1450        (if_then_else
1451	    (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1452	         (le (minus (match_dup 1) (pc)) (const_int 128))
1453	         (not (match_test "which_alternative")))
1454	    (const_int 2)
1455	    (const_int 8)))
1456   (set_attr "type" "branch,multiple")]
1457)
1458
1459(define_insn "*thumb2_one_cmplsi2_short"
1460  [(set (match_operand:SI 0 "low_register_operand" "=l")
1461	(not:SI (match_operand:SI 1 "low_register_operand" "l")))
1462   (clobber (reg:CC CC_REGNUM))]
1463  "TARGET_THUMB2 && reload_completed"
1464  "mvn%!\t%0, %1"
1465  [(set_attr "predicable" "yes")
1466   (set_attr "length" "2")
1467   (set_attr "type" "mvn_reg")]
1468)
1469
1470(define_insn "*thumb2_negsi2_short"
1471  [(set (match_operand:SI 0 "low_register_operand" "=l")
1472	(neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1473   (clobber (reg:CC CC_REGNUM))]
1474  "TARGET_THUMB2 && reload_completed"
1475  "rsb%!\t%0, %1, #0"
1476  [(set_attr "predicable" "yes")
1477   (set_attr "length" "2")
1478   (set_attr "type" "alu_sreg")]
1479)
1480
1481(define_insn "*orsi_notsi_si"
1482  [(set (match_operand:SI 0 "s_register_operand" "=r")
1483	(ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1484		(match_operand:SI 1 "s_register_operand" "r")))]
1485  "TARGET_THUMB2"
1486  "orn%?\\t%0, %1, %2"
1487  [(set_attr "predicable" "yes")
1488   (set_attr "type" "logic_reg")]
1489)
1490
1491(define_insn "*orsi_not_shiftsi_si"
1492  [(set (match_operand:SI 0 "s_register_operand" "=r")
1493	(ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1494			 [(match_operand:SI 2 "s_register_operand" "r")
1495			  (match_operand:SI 3 "const_int_operand" "M")]))
1496		(match_operand:SI 1 "s_register_operand" "r")))]
1497  "TARGET_THUMB2"
1498  "orn%?\\t%0, %1, %2%S4"
1499  [(set_attr "predicable" "yes")
1500   (set_attr "shift" "2")
1501   (set_attr "type" "alu_shift_imm")]
1502)
1503
1504(define_peephole2
1505  [(set (match_operand:CC_NZ 0 "cc_register" "")
1506	(compare:CC_NZ (zero_extract:SI
1507			  (match_operand:SI 1 "low_register_operand" "")
1508			  (const_int 1)
1509			  (match_operand:SI 2 "const_int_operand" ""))
1510			 (const_int 0)))
1511   (match_scratch:SI 3 "l")
1512   (set (pc)
1513	(if_then_else (match_operator:CC_NZ 4 "equality_operator"
1514		       [(match_dup 0) (const_int 0)])
1515		      (match_operand 5 "" "")
1516		      (match_operand 6 "" "")))]
1517  "TARGET_THUMB2
1518   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1519   && peep2_reg_dead_p (2, operands[0])"
1520  [(parallel [(set (match_dup 0)
1521		   (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1522				    (const_int 0)))
1523	      (clobber (match_dup 3))])
1524   (set (pc)
1525	(if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1526		      (match_dup 5) (match_dup 6)))]
1527  "
1528  operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1529  operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1530				VOIDmode, operands[0], const0_rtx);
1531  ")
1532
1533(define_peephole2
1534  [(set (match_operand:CC_NZ 0 "cc_register" "")
1535	(compare:CC_NZ (zero_extract:SI
1536			  (match_operand:SI 1 "low_register_operand" "")
1537			  (match_operand:SI 2 "const_int_operand" "")
1538			  (const_int 0))
1539			 (const_int 0)))
1540   (match_scratch:SI 3 "l")
1541   (set (pc)
1542	(if_then_else (match_operator:CC_NZ 4 "equality_operator"
1543		       [(match_dup 0) (const_int 0)])
1544		      (match_operand 5 "" "")
1545		      (match_operand 6 "" "")))]
1546  "TARGET_THUMB2
1547   && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1548   && peep2_reg_dead_p (2, operands[0])"
1549  [(parallel [(set (match_dup 0)
1550		   (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1551				  (const_int 0)))
1552	      (clobber (match_dup 3))])
1553   (set (pc)
1554	(if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1555		      (match_dup 5) (match_dup 6)))]
1556  "
1557  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1558  ")
1559
1560;; Define the subtract-one-and-jump insns so loop.c
1561;; knows what to generate.
1562(define_expand "doloop_end"
1563  [(use (match_operand 0 "" ""))      ; loop pseudo
1564   (use (match_operand 1 "" ""))]     ; label
1565  "TARGET_32BIT"
1566  "
1567 {
1568   /* Currently SMS relies on the do-loop pattern to recognize loops
1569      where (1) the control part consists of all insns defining and/or
1570      using a certain 'count' register and (2) the loop count can be
1571      adjusted by modifying this register prior to the loop.
1572      ??? The possible introduction of a new block to initialize the
1573      new IV can potentially affect branch optimizations.  */
1574   if (optimize > 0 && flag_modulo_sched)
1575   {
1576     rtx s0;
1577     rtx bcomp;
1578     rtx loc_ref;
1579     rtx cc_reg;
1580     rtx insn;
1581     rtx cmp;
1582
1583     if (GET_MODE (operands[0]) != SImode)
1584       FAIL;
1585
1586     s0 = operands [0];
1587     if (TARGET_THUMB2)
1588       insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1589     else
1590       insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1591
1592     cmp = XVECEXP (PATTERN (insn), 0, 0);
1593     cc_reg = SET_DEST (cmp);
1594     bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1595     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1596     emit_jump_insn (gen_rtx_SET (pc_rtx,
1597                                  gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1598                                                        loc_ref, pc_rtx)));
1599     DONE;
1600   }else
1601      FAIL;
1602 }")
1603
1604(define_insn "*clear_apsr"
1605  [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1606  (clobber (reg:CC CC_REGNUM))]
1607  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1608  "clrm%?\\t{APSR}"
1609  [(set_attr "predicable" "yes")]
1610)
1611
1612;; The operands are validated through the clear_multiple_operation
1613;; match_parallel predicate rather than through constraints so enable it only
1614;; after reload.
1615(define_insn "*clear_multiple"
1616  [(match_parallel 0 "clear_multiple_operation"
1617     [(set (match_operand:SI 1 "register_operand" "")
1618	   (const_int 0))])]
1619  "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1620  {
1621    char pattern[100];
1622    int i, num_saves = XVECLEN (operands[0], 0);
1623
1624    strcpy (pattern, \"clrm%?\\t{\");
1625    for (i = 0; i < num_saves; i++)
1626      {
1627	if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1628	  {
1629	    strcat (pattern, \"APSR\");
1630	    ++i;
1631	  }
1632	else
1633	  strcat (pattern,
1634		  reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1635	if (i < num_saves - 1)
1636	  strcat (pattern, \", %|\");
1637      }
1638    strcat (pattern, \"}\");
1639    output_asm_insn (pattern, operands);
1640    return \"\";
1641  }
1642  [(set_attr "predicable" "yes")]
1643)
1644
1645(define_insn "thumb2_asrl"
1646  [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1647	(ashiftrt:DI (match_dup 0)
1648		     (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1649  "TARGET_HAVE_MVE"
1650  "asrl%?\\t%Q0, %R0, %1"
1651  [(set_attr "predicable" "yes")])
1652
1653(define_insn "thumb2_lsll"
1654  [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1655	(ashift:DI (match_dup 0)
1656		   (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1657  "TARGET_HAVE_MVE"
1658  "lsll%?\\t%Q0, %R0, %1"
1659  [(set_attr "predicable" "yes")])
1660
1661(define_insn "thumb2_lsrl"
1662  [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1663	(lshiftrt:DI (match_dup 0)
1664		     (match_operand:SI 1 "long_shift_imm" "Pg")))]
1665  "TARGET_HAVE_MVE"
1666  "lsrl%?\\t%Q0, %R0, %1"
1667  [(set_attr "predicable" "yes")])
1668