1;; ARM Thumb-2 Machine Description
2;; Copyright (C) 2007-2018 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;; Thumb-2 only allows shift by constant on data processing instructions
28(define_insn "*thumb_andsi_not_shiftsi_si"
29  [(set (match_operand:SI 0 "s_register_operand" "=r")
30	(and:SI (not:SI (match_operator:SI 4 "shift_operator"
31			 [(match_operand:SI 2 "s_register_operand" "r")
32			  (match_operand:SI 3 "const_int_operand" "M")]))
33		(match_operand:SI 1 "s_register_operand" "r")))]
34  "TARGET_THUMB2"
35  "bic%?\\t%0, %1, %2%S4"
36  [(set_attr "predicable" "yes")
37   (set_attr "shift" "2")
38   (set_attr "type" "alu_shift_imm")]
39)
40
41;; We use the '0' constraint for operand 1 because reload should
42;; be smart enough to generate an appropriate move for the r/r/r case.
43(define_insn_and_split "*thumb2_smaxsi3"
44  [(set (match_operand:SI          0 "s_register_operand" "=r,l,r")
45	(smax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
46		 (match_operand:SI 2 "arm_rhs_operand"    "r,Py,I")))
47   (clobber (reg:CC CC_REGNUM))]
48   "TARGET_THUMB2"
49   "#"
50   ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
51  "TARGET_THUMB2 && reload_completed"
52  [(set (reg:CC CC_REGNUM)
53        (compare:CC (match_dup 1) (match_dup 2)))
54   (cond_exec (lt:SI (reg:CC CC_REGNUM) (const_int 0))
55              (set (match_dup 0)
56                   (match_dup 2)))]
57  ""
58  [(set_attr "conds" "clob")
59   (set_attr "enabled_for_short_it" "yes,yes,no")
60   (set_attr "length" "6,6,10")
61   (set_attr "type" "multiple")]
62)
63
64(define_insn_and_split "*thumb2_sminsi3"
65  [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
66	(smin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
67		 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
68   (clobber (reg:CC CC_REGNUM))]
69  "TARGET_THUMB2"
70  "#"
71  ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
72  "TARGET_THUMB2 && reload_completed"
73  [(set (reg:CC CC_REGNUM)
74        (compare:CC (match_dup 1) (match_dup 2)))
75   (cond_exec (ge:SI (reg:CC CC_REGNUM) (const_int 0))
76              (set (match_dup 0)
77                   (match_dup 2)))]
78  ""
79  [(set_attr "conds" "clob")
80   (set_attr "enabled_for_short_it" "yes,yes,no")
81   (set_attr "length" "6,6,10")
82   (set_attr "type" "multiple")]
83)
84
85(define_insn_and_split "*thumb32_umaxsi3"
86  [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
87	(umax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
88		 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
89  (clobber (reg:CC CC_REGNUM))]
90  "TARGET_THUMB2"
91  "#"
92  ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
93  "TARGET_THUMB2 && reload_completed"
94  [(set (reg:CC CC_REGNUM)
95        (compare:CC (match_dup 1) (match_dup 2)))
96   (cond_exec (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
97              (set (match_dup 0)
98                   (match_dup 2)))]
99  ""
100  [(set_attr "conds" "clob")
101   (set_attr "length" "6,6,10")
102   (set_attr "enabled_for_short_it" "yes,yes,no")
103   (set_attr "type" "multiple")]
104)
105
106(define_insn_and_split "*thumb2_uminsi3"
107  [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
108	(umin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
109		 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
110   (clobber (reg:CC CC_REGNUM))]
111  "TARGET_THUMB2"
112  "#"
113  ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
114  "TARGET_THUMB2 && reload_completed"
115  [(set (reg:CC CC_REGNUM)
116        (compare:CC (match_dup 1) (match_dup 2)))
117   (cond_exec (geu:SI (reg:CC CC_REGNUM) (const_int 0))
118              (set (match_dup 0)
119                   (match_dup 2)))]
120  ""
121  [(set_attr "conds" "clob")
122   (set_attr "length" "6,6,10")
123   (set_attr "enabled_for_short_it" "yes,yes,no")
124   (set_attr "type" "multiple")]
125)
126
127(define_insn_and_split "*thumb2_abssi2"
128  [(set (match_operand:SI         0 "s_register_operand" "=&r,l,r")
129	(abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0")))
130   (clobber (reg:CC CC_REGNUM))]
131  "TARGET_THUMB2"
132  "#"
133   ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
134   ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
135   ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
136  "&& reload_completed"
137  [(const_int 0)]
138  {
139    if (REGNO(operands[0]) == REGNO(operands[1]))
140      {
141       rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
142
143       emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
144       							const0_rtx)));
145       emit_insn (gen_rtx_COND_EXEC (VOIDmode,
146                                    (gen_rtx_LT (SImode,
147                                                 cc_reg,
148                                                 const0_rtx)),
149                                    (gen_rtx_SET (operands[0],
150                                                  (gen_rtx_MINUS (SImode,
151                                                                  const0_rtx,
152                                                                  operands[1]))))));
153      }
154    else
155      {
156        emit_insn (gen_rtx_SET (operands[0],
157                                gen_rtx_XOR (SImode,
158                                             gen_rtx_ASHIFTRT (SImode,
159                                                               operands[1],
160                                                               GEN_INT (31)),
161                                             operands[1])));
162        emit_insn (gen_rtx_SET (operands[0],
163                                gen_rtx_MINUS (SImode,
164                                               operands[0],
165                                               gen_rtx_ASHIFTRT (SImode,
166                                                                 operands[1],
167                                                                 GEN_INT (31)))));
168      }
169    DONE;
170  }
171  [(set_attr "conds" "*,clob,clob")
172   (set_attr "shift" "1")
173   (set_attr "predicable" "yes,no,no")
174   (set_attr "enabled_for_short_it" "yes,yes,no")
175   (set_attr "ce_count" "2")
176   (set_attr "length" "8,6,10")
177   (set_attr "type" "multiple")]
178)
179
180(define_insn_and_split "*thumb2_neg_abssi2"
181  [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
182	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0"))))
183   (clobber (reg:CC CC_REGNUM))]
184  "TARGET_THUMB2"
185  "#"
186   ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
187   ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
188   ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
189  "&& reload_completed"
190  [(const_int 0)]
191  {
192    if (REGNO(operands[0]) == REGNO(operands[1]))
193      {
194       rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
195
196       emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
197							const0_rtx)));
198       emit_insn (gen_rtx_COND_EXEC (VOIDmode,
199                                    (gen_rtx_GT (SImode,
200                                                 cc_reg,
201                                                 const0_rtx)),
202                                    (gen_rtx_SET (operands[0],
203                                                  (gen_rtx_MINUS (SImode,
204                                                                  const0_rtx,
205                                                                  operands[1]))))));
206      }
207    else
208      {
209        emit_insn (gen_rtx_SET (operands[0],
210                                gen_rtx_XOR (SImode,
211                                             gen_rtx_ASHIFTRT (SImode,
212                                                               operands[1],
213                                                               GEN_INT (31)),
214                                             operands[1])));
215        emit_insn (gen_rtx_SET (operands[0],
216                                gen_rtx_MINUS (SImode,
217                                               gen_rtx_ASHIFTRT (SImode,
218                                                                 operands[1],
219                                                                 GEN_INT (31)),
220                                               operands[0])));
221      }
222    DONE;
223  }
224  [(set_attr "conds" "*,clob,clob")
225   (set_attr "shift" "1")
226   (set_attr "predicable" "yes,no,no")
227   (set_attr "enabled_for_short_it" "yes,yes,no")
228   (set_attr "ce_count" "2")
229   (set_attr "length" "8,6,10")
230   (set_attr "type" "multiple")]
231)
232
233;; Pop a single register as its size is preferred over a post-incremental load
234(define_insn "*thumb2_pop_single"
235  [(set (match_operand:SI 0 "low_register_operand" "=r")
236        (mem:SI (post_inc:SI (reg:SI SP_REGNUM))))]
237  "TARGET_THUMB2 && (reload_in_progress || reload_completed)"
238  "pop\t{%0}"
239  [(set_attr "type" "load_4")
240   (set_attr "length" "2")
241   (set_attr "predicable" "yes")]
242)
243
244;; We have two alternatives here for memory loads (and similarly for stores)
245;; to reflect the fact that the permissible constant pool ranges differ
246;; between ldr instructions taking low regs and ldr instructions taking high
247;; regs.  The high register alternatives are not taken into account when
248;; choosing register preferences in order to reflect their expense.
249(define_insn "*thumb2_movsi_insn"
250  [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,l ,*hk,m,*m")
251	(match_operand:SI 1 "general_operand"	   "rk,I,Py,K,j,mi,*mi,l,*hk"))]
252  "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
253   && (   register_operand (operands[0], SImode)
254       || register_operand (operands[1], SImode))"
255  "@
256   mov%?\\t%0, %1
257   mov%?\\t%0, %1
258   mov%?\\t%0, %1
259   mvn%?\\t%0, #%B1
260   movw%?\\t%0, %1
261   ldr%?\\t%0, %1
262   ldr%?\\t%0, %1
263   str%?\\t%1, %0
264   str%?\\t%1, %0"
265  [(set_attr "type" "mov_reg,mov_imm,mov_imm,mvn_imm,mov_imm,load_4,load_4,store_4,store_4")
266   (set_attr "length" "2,4,2,4,4,4,4,4,4")
267   (set_attr "predicable" "yes")
268   (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no")
269   (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*")
270   (set_attr "neg_pool_range" "*,*,*,*,*,0,0,*,*")]
271)
272
273(define_insn "tls_load_dot_plus_four"
274  [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
275	(mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
276			    (const_int 4)
277			    (match_operand 3 "" "")]
278			   UNSPEC_PIC_BASE)))
279   (clobber (match_scratch:SI 1 "=X,l,X,r"))]
280  "TARGET_THUMB2"
281  "*
282  (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
283			     INTVAL (operands[3]));
284  return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
285  "
286  [(set_attr "length" "4,4,6,6")
287   (set_attr "type" "multiple")]
288)
289
290;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
291;; of the messiness associated with the ARM patterns.
292(define_insn "*thumb2_movhi_insn"
293  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,l,r,m,r")
294	(match_operand:HI 1 "general_operand"      "rk,I,Py,n,r,m"))]
295  "TARGET_THUMB2
296  && (register_operand (operands[0], HImode)
297     || register_operand (operands[1], HImode))"
298  "@
299   mov%?\\t%0, %1\\t%@ movhi
300   mov%?\\t%0, %1\\t%@ movhi
301   mov%?\\t%0, %1\\t%@ movhi
302   movw%?\\t%0, %L1\\t%@ movhi
303   strh%?\\t%1, %0\\t%@ movhi
304   ldrh%?\\t%0, %1\\t%@ movhi"
305  [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store_4,load_4")
306   (set_attr "predicable" "yes")
307   (set_attr "predicable_short_it" "yes,no,yes,no,no,no")
308   (set_attr "length" "2,4,2,4,4,4")
309   (set_attr "pool_range" "*,*,*,*,*,4094")
310   (set_attr "neg_pool_range" "*,*,*,*,*,250")]
311)
312
313(define_insn "*thumb2_storewb_pairsi"
314  [(set (match_operand:SI 0 "register_operand" "=&kr")
315	(plus:SI (match_operand:SI 1 "register_operand" "0")
316		 (match_operand:SI 2 "const_int_operand" "n")))
317   (set (mem:SI (plus:SI (match_dup 0) (match_dup 2)))
318	(match_operand:SI 3 "register_operand" "r"))
319   (set (mem:SI (plus:SI (match_dup 0)
320			 (match_operand:SI 5 "const_int_operand" "n")))
321	(match_operand:SI 4 "register_operand" "r"))]
322  "TARGET_THUMB2
323   && INTVAL (operands[5]) == INTVAL (operands[2]) + 4"
324  "strd\\t%3, %4, [%0, %2]!"
325  [(set_attr "type" "store_8")]
326)
327
328(define_insn "*thumb2_cmpsi_neg_shiftsi"
329  [(set (reg:CC CC_REGNUM)
330	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
331		    (neg:SI (match_operator:SI 3 "shift_operator"
332			     [(match_operand:SI 1 "s_register_operand" "r")
333			      (match_operand:SI 2 "const_int_operand" "M")]))))]
334  "TARGET_THUMB2"
335  "cmn%?\\t%0, %1%S3"
336  [(set_attr "conds" "set")
337   (set_attr "shift" "1")
338   (set_attr "type" "alus_shift_imm")]
339)
340
341(define_insn_and_split "*thumb2_mov_scc"
342  [(set (match_operand:SI 0 "s_register_operand" "=l,r")
343	(match_operator:SI 1 "arm_comparison_operator_mode"
344	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
345  "TARGET_THUMB2"
346  "#"   ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
347  "TARGET_THUMB2"
348  [(set (match_dup 0)
349        (if_then_else:SI (match_dup 1)
350                         (const_int 1)
351                         (const_int 0)))]
352  ""
353  [(set_attr "conds" "use")
354   (set_attr "enabled_for_short_it" "yes,no")
355   (set_attr "length" "8,10")
356   (set_attr "type" "multiple")]
357)
358
359(define_insn_and_split "*thumb2_mov_negscc"
360  [(set (match_operand:SI 0 "s_register_operand" "=r")
361	(neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
362		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
363  "TARGET_THUMB2 && !arm_restrict_it"
364  "#"   ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
365  "&& true"
366  [(set (match_dup 0)
367        (if_then_else:SI (match_dup 1)
368                         (match_dup 3)
369                         (const_int 0)))]
370  {
371    operands[3] = GEN_INT (~0);
372  }
373  [(set_attr "conds" "use")
374   (set_attr "length" "10")
375   (set_attr "type" "multiple")]
376)
377
378(define_insn_and_split "*thumb2_mov_negscc_strict_it"
379  [(set (match_operand:SI 0 "low_register_operand" "=l")
380	(neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
381		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
382  "TARGET_THUMB2 && arm_restrict_it"
383  "#"   ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\"
384  "&& reload_completed"
385  [(set (match_dup 0)
386        (match_dup 3))
387   (cond_exec (match_dup 4)
388              (set (match_dup 0)
389                   (const_int 0)))]
390  {
391    operands[3] = GEN_INT (~0);
392    machine_mode mode = GET_MODE (operands[2]);
393    enum rtx_code rc = GET_CODE (operands[1]);
394
395    if (mode == CCFPmode || mode == CCFPEmode)
396      rc = reverse_condition_maybe_unordered (rc);
397    else
398      rc = reverse_condition (rc);
399    operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
400
401  }
402  [(set_attr "conds" "use")
403   (set_attr "length" "8")
404   (set_attr "type" "multiple")]
405)
406
407(define_insn_and_split "*thumb2_mov_notscc"
408  [(set (match_operand:SI 0 "s_register_operand" "=r")
409	(not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
410		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
411  "TARGET_THUMB2 && !arm_restrict_it"
412  "#"   ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
413  "&& true"
414  [(set (match_dup 0)
415        (if_then_else:SI (match_dup 1)
416                         (match_dup 3)
417                         (match_dup 4)))]
418  {
419    operands[3] = GEN_INT (~1);
420    operands[4] = GEN_INT (~0);
421  }
422  [(set_attr "conds" "use")
423   (set_attr "length" "10")
424   (set_attr "type" "multiple")]
425)
426
427(define_insn_and_split "*thumb2_mov_notscc_strict_it"
428  [(set (match_operand:SI 0 "low_register_operand" "=l")
429	(not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
430                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
431  "TARGET_THUMB2 && arm_restrict_it"
432  "#"   ; "mvn %0, #0 ; it%d1 ; lsl%d1 %0, %0, #1"
433  "&& reload_completed"
434  [(set (match_dup 0)
435        (match_dup 3))
436   (cond_exec (match_dup 4)
437              (set (match_dup 0)
438                   (ashift:SI (match_dup 0)
439                              (const_int 1))))]
440  {
441    operands[3] = GEN_INT (~0);
442    operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
443                                  VOIDmode, operands[2], const0_rtx);
444  }
445  [(set_attr "conds" "use")
446   (set_attr "length" "8")
447   (set_attr "type" "multiple")]
448)
449
450(define_insn_and_split "*thumb2_movsicc_insn"
451  [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r")
452	(if_then_else:SI
453	 (match_operator 3 "arm_comparison_operator"
454	  [(match_operand 4 "cc_register" "") (const_int 0)])
455	 (match_operand:SI 1 "arm_not_operand" "0 ,lPy,0 ,0,rI,K,I ,r,rI,K ,K,r")
456	 (match_operand:SI 2 "arm_not_operand" "lPy,0 ,rI,K,0 ,0,rI,I,K ,rI,K,r")))]
457  "TARGET_THUMB2"
458  "@
459   it\\t%D3\;mov%D3\\t%0, %2
460   it\\t%d3\;mov%d3\\t%0, %1
461   it\\t%D3\;mov%D3\\t%0, %2
462   it\\t%D3\;mvn%D3\\t%0, #%B2
463   it\\t%d3\;mov%d3\\t%0, %1
464   it\\t%d3\;mvn%d3\\t%0, #%B1
465   #
466   #
467   #
468   #
469   #
470   #"
471   ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
472   ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
473   ; alt 8: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
474   ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
475   ; alt 10: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
476   ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
477  "&& reload_completed"
478  [(const_int 0)]
479  {
480    enum rtx_code rev_code;
481    machine_mode mode;
482    rtx rev_cond;
483
484    emit_insn (gen_rtx_COND_EXEC (VOIDmode,
485                                  operands[3],
486                                  gen_rtx_SET (operands[0], operands[1])));
487    rev_code = GET_CODE (operands[3]);
488    mode = GET_MODE (operands[4]);
489    if (mode == CCFPmode || mode == CCFPEmode)
490      rev_code = reverse_condition_maybe_unordered (rev_code);
491    else
492      rev_code = reverse_condition (rev_code);
493
494    rev_cond = gen_rtx_fmt_ee (rev_code,
495                               VOIDmode,
496                               gen_rtx_REG (mode, CC_REGNUM),
497                               const0_rtx);
498    emit_insn (gen_rtx_COND_EXEC (VOIDmode,
499                                  rev_cond,
500                                  gen_rtx_SET (operands[0], operands[2])));
501    DONE;
502  }
503  [(set_attr "length" "4,4,6,6,6,6,10,8,10,10,10,6")
504   (set_attr "enabled_for_short_it" "yes,yes,no,no,no,no,no,no,no,no,no,yes")
505   (set_attr "conds" "use")
506   (set_attr_alternative "type"
507                         [(if_then_else (match_operand 2 "const_int_operand" "")
508                                        (const_string "mov_imm")
509                                        (const_string "mov_reg"))
510                          (if_then_else (match_operand 1 "const_int_operand" "")
511                                        (const_string "mov_imm")
512                                        (const_string "mov_reg"))
513                          (if_then_else (match_operand 2 "const_int_operand" "")
514                                        (const_string "mov_imm")
515                                        (const_string "mov_reg"))
516                          (const_string "mvn_imm")
517                          (if_then_else (match_operand 1 "const_int_operand" "")
518                                        (const_string "mov_imm")
519                                        (const_string "mov_reg"))
520                          (const_string "mvn_imm")
521                          (const_string "multiple")
522                          (const_string "multiple")
523                          (const_string "multiple")
524                          (const_string "multiple")
525                          (const_string "multiple")
526                          (const_string "multiple")])]
527)
528
529(define_insn "*thumb2_movsfcc_soft_insn"
530  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
531	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
532			  [(match_operand 4 "cc_register" "") (const_int 0)])
533			 (match_operand:SF 1 "s_register_operand" "0,r")
534			 (match_operand:SF 2 "s_register_operand" "r,0")))]
535  "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
536  "@
537   it\\t%D3\;mov%D3\\t%0, %2
538   it\\t%d3\;mov%d3\\t%0, %1"
539  [(set_attr "length" "6,6")
540   (set_attr "conds" "use")
541   (set_attr "type" "multiple")]
542)
543
544(define_insn "*call_reg_thumb2"
545  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
546         (match_operand 1 "" ""))
547   (use (match_operand 2 "" ""))
548   (clobber (reg:SI LR_REGNUM))]
549  "TARGET_THUMB2"
550  "blx%?\\t%0"
551  [(set_attr "type" "call")]
552)
553
554(define_insn "*nonsecure_call_reg_thumb2"
555  [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
556		    UNSPEC_NONSECURE_MEM)
557	 (match_operand 0 "" ""))
558   (use (match_operand 1 "" ""))
559   (clobber (reg:SI LR_REGNUM))]
560  "TARGET_THUMB2 && use_cmse"
561  "bl\\t__gnu_cmse_nonsecure_call"
562  [(set_attr "length" "4")
563   (set_attr "type" "call")]
564)
565
566(define_insn "*call_value_reg_thumb2"
567  [(set (match_operand 0 "" "")
568	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
569	      (match_operand 2 "" "")))
570   (use (match_operand 3 "" ""))
571   (clobber (reg:SI LR_REGNUM))]
572  "TARGET_THUMB2"
573  "blx\\t%1"
574  [(set_attr "type" "call")]
575)
576
577(define_insn "*nonsecure_call_value_reg_thumb2"
578  [(set (match_operand 0 "" "")
579	(call
580	 (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
581		    UNSPEC_NONSECURE_MEM)
582	 (match_operand 1 "" "")))
583   (use (match_operand 2 "" ""))
584   (clobber (reg:SI LR_REGNUM))]
585  "TARGET_THUMB2 && use_cmse"
586  "bl\t__gnu_cmse_nonsecure_call"
587  [(set_attr "length" "4")
588   (set_attr "type" "call")]
589)
590
591(define_insn "*thumb2_indirect_jump"
592  [(set (pc)
593	(match_operand:SI 0 "register_operand" "l*r"))]
594  "TARGET_THUMB2"
595  "bx\\t%0"
596  [(set_attr "conds" "clob")
597   (set_attr "type" "branch")]
598)
599;; Don't define thumb2_load_indirect_jump because we can't guarantee label
600;; addresses will have the thumb bit set correctly.
601
602
603(define_insn_and_split "*thumb2_and_scc"
604  [(set (match_operand:SI 0 "s_register_operand" "=Ts")
605	(and:SI (match_operator:SI 1 "arm_comparison_operator"
606		 [(match_operand 2 "cc_register" "") (const_int 0)])
607		(match_operand:SI 3 "s_register_operand" "r")))]
608  "TARGET_THUMB2"
609  "#"   ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
610  "&& reload_completed"
611  [(set (match_dup 0)
612        (and:SI (match_dup 3) (const_int 1)))
613   (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
614  {
615    machine_mode mode = GET_MODE (operands[2]);
616    enum rtx_code rc = GET_CODE (operands[1]);
617
618    if (mode == CCFPmode || mode == CCFPEmode)
619      rc = reverse_condition_maybe_unordered (rc);
620    else
621      rc = reverse_condition (rc);
622    operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
623  }
624  [(set_attr "conds" "use")
625   (set_attr "type" "multiple")
626   (set (attr "length") (if_then_else (match_test "arm_restrict_it")
627                                      (const_int 8)
628                                      (const_int 10)))]
629)
630
631(define_insn_and_split "*thumb2_ior_scc"
632  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
633	(ior:SI (match_operator:SI 1 "arm_comparison_operator"
634		 [(match_operand 2 "cc_register" "") (const_int 0)])
635		(match_operand:SI 3 "s_register_operand" "0,?r")))]
636  "TARGET_THUMB2 && !arm_restrict_it"
637  "@
638   it\\t%d1\;orr%d1\\t%0, %3, #1
639   #"
640   ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
641   "&& reload_completed
642    && REGNO (operands [0]) != REGNO (operands[3])"
643   [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
644    (cond_exec (match_dup 4) (set (match_dup 0)
645                                  (ior:SI (match_dup 3) (const_int 1))))]
646  {
647    machine_mode mode = GET_MODE (operands[2]);
648    enum rtx_code rc = GET_CODE (operands[1]);
649
650    operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
651    if (mode == CCFPmode || mode == CCFPEmode)
652      rc = reverse_condition_maybe_unordered (rc);
653    else
654      rc = reverse_condition (rc);
655    operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
656  }
657  [(set_attr "conds" "use")
658   (set_attr "length" "6,10")
659   (set_attr "type" "multiple")]
660)
661
662(define_insn_and_split "*thumb2_ior_scc_strict_it"
663  [(set (match_operand:SI 0 "s_register_operand" "=&r")
664	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
665		 [(match_operand 3 "cc_register" "") (const_int 0)])
666		(match_operand:SI 1 "s_register_operand" "r")))]
667  "TARGET_THUMB2 && arm_restrict_it"
668  "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
669  "&& reload_completed"
670  [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
671   (cond_exec (match_dup 4)
672     (set (match_dup 0) (match_dup 1)))]
673  {
674    machine_mode mode = GET_MODE (operands[3]);
675    rtx_code rc = GET_CODE (operands[2]);
676
677    if (mode == CCFPmode || mode == CCFPEmode)
678      rc = reverse_condition_maybe_unordered (rc);
679    else
680      rc = reverse_condition (rc);
681    operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
682  }
683  [(set_attr "conds" "use")
684   (set_attr "length" "8")
685   (set_attr "type" "multiple")]
686)
687
688(define_insn "*thumb2_cond_move"
689  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
690	(if_then_else:SI (match_operator 3 "equality_operator"
691			  [(match_operator 4 "arm_comparison_operator"
692			    [(match_operand 5 "cc_register" "") (const_int 0)])
693			   (const_int 0)])
694			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
695			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
696  "TARGET_THUMB2"
697  "*
698    if (GET_CODE (operands[3]) == NE)
699      {
700        if (which_alternative != 1)
701	  output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
702        if (which_alternative != 0)
703	  output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
704        return \"\";
705      }
706    switch (which_alternative)
707      {
708      case 0:
709	output_asm_insn (\"it\\t%d4\", operands);
710	break;
711      case 1:
712	output_asm_insn (\"it\\t%D4\", operands);
713	break;
714      case 2:
715	if (arm_restrict_it)
716	  output_asm_insn (\"it\\t%D4\", operands);
717	else
718	  output_asm_insn (\"ite\\t%D4\", operands);
719	break;
720      default:
721	abort();
722      }
723    if (which_alternative != 0)
724      {
725        output_asm_insn (\"mov%D4\\t%0, %1\", operands);
726        if (arm_restrict_it && which_alternative == 2)
727          output_asm_insn (\"it\\t%d4\", operands);
728      }
729    if (which_alternative != 1)
730      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
731    return \"\";
732  "
733  [(set_attr "conds" "use")
734   (set_attr "length" "6,6,10")
735   (set_attr "type" "multiple")]
736)
737
738(define_insn "*thumb2_cond_arith"
739  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
740        (match_operator:SI 5 "shiftable_operator"
741	 [(match_operator:SI 4 "arm_comparison_operator"
742           [(match_operand:SI 2 "s_register_operand" "r,r")
743	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
744          (match_operand:SI 1 "s_register_operand" "0,?r")]))
745   (clobber (reg:CC CC_REGNUM))]
746  "TARGET_THUMB2 && !arm_restrict_it"
747  "*
748    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
749      return \"%i5\\t%0, %1, %2, lsr #31\";
750
751    output_asm_insn (\"cmp\\t%2, %3\", operands);
752    if (GET_CODE (operands[5]) == AND)
753      {
754	output_asm_insn (\"ite\\t%D4\", operands);
755	output_asm_insn (\"mov%D4\\t%0, #0\", operands);
756      }
757    else if (GET_CODE (operands[5]) == MINUS)
758      {
759	output_asm_insn (\"ite\\t%D4\", operands);
760	output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
761      }
762    else if (which_alternative != 0)
763      {
764	output_asm_insn (\"ite\\t%D4\", operands);
765	output_asm_insn (\"mov%D4\\t%0, %1\", operands);
766      }
767    else
768      output_asm_insn (\"it\\t%d4\", operands);
769    return \"%i5%d4\\t%0, %1, #1\";
770  "
771  [(set_attr "conds" "clob")
772   (set_attr "length" "14")
773   (set_attr "type" "multiple")]
774)
775
776(define_insn_and_split "*thumb2_cond_arith_strict_it"
777  [(set (match_operand:SI 0 "s_register_operand" "=l")
778        (match_operator:SI 5 "shiftable_operator_strict_it"
779	 [(match_operator:SI 4 "arm_comparison_operator"
780           [(match_operand:SI 2 "s_register_operand" "r")
781	    (match_operand:SI 3 "arm_rhs_operand" "rI")])
782          (match_operand:SI 1 "s_register_operand" "0")]))
783   (clobber (reg:CC CC_REGNUM))]
784  "TARGET_THUMB2 && arm_restrict_it"
785  "#"
786  "&& reload_completed"
787  [(const_int 0)]
788  {
789    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
790      {
791        /*  %i5 %0, %1, %2, lsr #31  */
792        rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
793        rtx op = NULL_RTX;
794
795        switch (GET_CODE (operands[5]))
796          {
797          case AND:
798            op = gen_rtx_AND (SImode, shifted_op, operands[1]);
799            break;
800           case PLUS:
801            op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
802            break;
803          default: gcc_unreachable ();
804          }
805        emit_insn (gen_rtx_SET (operands[0], op));
806        DONE;
807      }
808
809    /*  "cmp  %2, %3"  */
810    emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
811                            gen_rtx_COMPARE (CCmode, operands[2],
812					     operands[3])));
813
814    if (GET_CODE (operands[5]) == AND)
815      {
816        /*  %i5  %0, %1, #1
817            it%D4
818            mov%D4  %0, #0  */
819        enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
820        emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
821							  GEN_INT (1))));
822        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
823                                      gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
824                                      gen_rtx_SET (operands[0], const0_rtx)));
825        DONE;
826      }
827    else
828      {
829        /*  it\\t%d4
830            %i5%d4\\t%0, %1, #1   */
831        emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
832                                                                VOIDmode,
833                                                                gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
834                                                gen_rtx_SET (operands[0],
835                                                            gen_rtx_PLUS (SImode,
836                                                                          operands[1],
837                                                                          GEN_INT (1)))));
838        DONE;
839      }
840     FAIL;
841  }
842  [(set_attr "conds" "clob")
843   (set_attr "length" "12")
844   (set_attr "type" "multiple")]
845)
846
847(define_insn "*thumb2_cond_sub"
848  [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
849        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
850		  (match_operator:SI 4 "arm_comparison_operator"
851                   [(match_operand:SI 2 "s_register_operand" "r,r")
852		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
853   (clobber (reg:CC CC_REGNUM))]
854  "TARGET_THUMB2"
855  "*
856    output_asm_insn (\"cmp\\t%2, %3\", operands);
857    if (which_alternative != 0)
858      {
859	if (arm_restrict_it)
860	  {
861	    output_asm_insn (\"mov\\t%0, %1\", operands);
862	    output_asm_insn (\"it\\t%d4\", operands);
863	  }
864	else
865	{
866	  output_asm_insn (\"ite\\t%D4\", operands);
867	  output_asm_insn (\"mov%D4\\t%0, %1\", operands);
868	}
869      }
870    else
871      output_asm_insn (\"it\\t%d4\", operands);
872    return \"sub%d4\\t%0, %1, #1\";
873  "
874  [(set_attr "conds" "clob")
875   (set_attr "length" "10,14")
876   (set_attr "type" "multiple")]
877)
878
879(define_insn_and_split "*thumb2_negscc"
880  [(set (match_operand:SI 0 "s_register_operand" "=Ts")
881	(neg:SI (match_operator 3 "arm_comparison_operator"
882		 [(match_operand:SI 1 "s_register_operand" "r")
883		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
884   (clobber (reg:CC CC_REGNUM))]
885  "TARGET_THUMB2"
886  "#"
887  "&& reload_completed"
888  [(const_int 0)]
889  {
890    rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
891
892    if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
893      {
894        /* Emit asr\\t%0, %1, #31 */
895        emit_insn (gen_rtx_SET (operands[0],
896                                gen_rtx_ASHIFTRT (SImode,
897                                                  operands[1],
898                                                  GEN_INT (31))));
899        DONE;
900      }
901    else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
902      {
903        /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
904        if (CONST_INT_P (operands[2]))
905          emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
906                                        GEN_INT (- INTVAL (operands[2]))));
907        else
908          emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
909
910        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
911                                      gen_rtx_NE (SImode,
912                                                  cc_reg,
913                                                  const0_rtx),
914                                      gen_rtx_SET (operands[0],
915                                                   GEN_INT (~0))));
916        DONE;
917      }
918    else
919      {
920       /* Emit:  cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
921       enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
922       machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
923       rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
924
925       emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
926							operands[2])));
927
928       emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
929
930       emit_insn (gen_rtx_COND_EXEC (VOIDmode,
931                                     gen_rtx_fmt_ee (rc,
932                                                     VOIDmode,
933                                                     tmp1,
934                                                     const0_rtx),
935                                     gen_rtx_SET (operands[0], const0_rtx)));
936       DONE;
937      }
938    FAIL;
939  }
940  [(set_attr "conds" "clob")
941   (set_attr "length" "14")
942   (set_attr "type" "multiple")]
943)
944
945(define_insn "*thumb2_movcond"
946  [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
947	(if_then_else:SI
948	 (match_operator 5 "arm_comparison_operator"
949	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
950	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
951	 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
952	 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
953   (clobber (reg:CC CC_REGNUM))]
954  "TARGET_THUMB2"
955  "*
956  if (GET_CODE (operands[5]) == LT
957      && (operands[4] == const0_rtx))
958    {
959      if (which_alternative != 1 && REG_P (operands[1]))
960	{
961	  if (operands[2] == const0_rtx)
962	    return \"and\\t%0, %1, %3, asr #31\";
963	  return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
964	}
965      else if (which_alternative != 0 && REG_P (operands[2]))
966	{
967	  if (operands[1] == const0_rtx)
968	    return \"bic\\t%0, %2, %3, asr #31\";
969	  return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
970	}
971      /* The only case that falls through to here is when both ops 1 & 2
972	 are constants.  */
973    }
974
975  if (GET_CODE (operands[5]) == GE
976      && (operands[4] == const0_rtx))
977    {
978      if (which_alternative != 1 && REG_P (operands[1]))
979	{
980	  if (operands[2] == const0_rtx)
981	    return \"bic\\t%0, %1, %3, asr #31\";
982	  return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
983	}
984      else if (which_alternative != 0 && REG_P (operands[2]))
985	{
986	  if (operands[1] == const0_rtx)
987	    return \"and\\t%0, %2, %3, asr #31\";
988	  return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
989	}
990      /* The only case that falls through to here is when both ops 1 & 2
991	 are constants.  */
992    }
993  if (CONST_INT_P (operands[4])
994      && !const_ok_for_arm (INTVAL (operands[4])))
995    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
996  else
997    output_asm_insn (\"cmp\\t%3, %4\", operands);
998  switch (which_alternative)
999    {
1000    case 0:
1001      output_asm_insn (\"it\\t%D5\", operands);
1002      break;
1003    case 1:
1004      output_asm_insn (\"it\\t%d5\", operands);
1005      break;
1006    case 2:
1007      if (arm_restrict_it)
1008        {
1009          output_asm_insn (\"mov\\t%0, %1\", operands);
1010          output_asm_insn (\"it\\t%D5\", operands);
1011        }
1012      else
1013        output_asm_insn (\"ite\\t%d5\", operands);
1014      break;
1015    default:
1016      abort();
1017    }
1018  if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1019    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1020  if (which_alternative != 1)
1021    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1022  return \"\";
1023  "
1024  [(set_attr "conds" "clob")
1025   (set_attr "length" "10,10,14")
1026   (set_attr "type" "multiple")]
1027)
1028
1029;; Zero and sign extension instructions.
1030
1031;; All supported Thumb2 implementations are armv6, so only that case is
1032;; provided.
1033(define_insn "*thumb2_extendqisi_v6"
1034  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1035	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1036  "TARGET_THUMB2 && arm_arch6"
1037  "@
1038   sxtb%?\\t%0, %1
1039   ldrsb%?\\t%0, %1"
1040  [(set_attr "type" "extend,load_byte")
1041   (set_attr "predicable" "yes")
1042   (set_attr "pool_range" "*,4094")
1043   (set_attr "neg_pool_range" "*,250")]
1044)
1045
1046(define_insn "*thumb2_zero_extendhisi2_v6"
1047  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1048	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1049  "TARGET_THUMB2 && arm_arch6"
1050  "@
1051   uxth%?\\t%0, %1
1052   ldrh%?\\t%0, %1"
1053  [(set_attr "type" "extend,load_byte")
1054   (set_attr "predicable" "yes")
1055   (set_attr "pool_range" "*,4094")
1056   (set_attr "neg_pool_range" "*,250")]
1057)
1058
1059(define_insn "thumb2_zero_extendqisi2_v6"
1060  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1061	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1062  "TARGET_THUMB2 && arm_arch6"
1063  "@
1064   uxtb%?\\t%0, %1
1065   ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1066  [(set_attr "type" "extend,load_byte")
1067   (set_attr "predicable" "yes")
1068   (set_attr "pool_range" "*,4094")
1069   (set_attr "neg_pool_range" "*,250")]
1070)
1071
1072(define_insn "thumb2_casesi_internal"
1073  [(parallel [(set (pc)
1074	       (if_then_else
1075		(leu (match_operand:SI 0 "s_register_operand" "r")
1076		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
1077		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1078				 (label_ref (match_operand 2 "" ""))))
1079		(label_ref (match_operand 3 "" ""))))
1080	      (clobber (reg:CC CC_REGNUM))
1081	      (clobber (match_scratch:SI 4 "=&r"))
1082	      (use (label_ref (match_dup 2)))])]
1083  "TARGET_THUMB2 && !flag_pic"
1084  "* return thumb2_output_casesi(operands);"
1085  [(set_attr "conds" "clob")
1086   (set_attr "length" "16")
1087   (set_attr "type" "multiple")]
1088)
1089
1090(define_insn "thumb2_casesi_internal_pic"
1091  [(parallel [(set (pc)
1092	       (if_then_else
1093		(leu (match_operand:SI 0 "s_register_operand" "r")
1094		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
1095		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1096				 (label_ref (match_operand 2 "" ""))))
1097		(label_ref (match_operand 3 "" ""))))
1098	      (clobber (reg:CC CC_REGNUM))
1099	      (clobber (match_scratch:SI 4 "=&r"))
1100	      (clobber (match_scratch:SI 5 "=r"))
1101	      (use (label_ref (match_dup 2)))])]
1102  "TARGET_THUMB2 && flag_pic"
1103  "* return thumb2_output_casesi(operands);"
1104  [(set_attr "conds" "clob")
1105   (set_attr "length" "20")
1106   (set_attr "type" "multiple")]
1107)
1108
1109(define_insn "*thumb2_return"
1110  [(simple_return)]
1111  "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1112  "* return output_return_instruction (const_true_rtx, true, false, true);"
1113  [(set_attr "type" "branch")
1114   (set_attr "length" "4")]
1115)
1116
1117(define_insn "*thumb2_cmse_entry_return"
1118  [(simple_return)]
1119  "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1120  "* return output_return_instruction (const_true_rtx, true, false, true);"
1121  [(set_attr "type" "branch")
1122   ; This is a return from a cmse_nonsecure_entry function so code will be
1123   ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1124   ; we adapt the length accordingly.
1125   (set (attr "length")
1126     (if_then_else (match_test "TARGET_HARD_FLOAT")
1127      (const_int 34)
1128      (const_int 8)))
1129   ; We do not support predicate execution of returns from cmse_nonsecure_entry
1130   ; functions because we need to clear the APSR.  Since predicable has to be
1131   ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1132   ; functions.
1133   (set_attr "predicable" "no")]
1134)
1135
1136(define_insn_and_split "thumb2_eh_return"
1137  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1138		    VUNSPEC_EH_RETURN)
1139   (clobber (match_scratch:SI 1 "=&r"))]
1140  "TARGET_THUMB2"
1141  "#"
1142  "&& reload_completed"
1143  [(const_int 0)]
1144  "
1145  {
1146    thumb_set_return_address (operands[0], operands[1]);
1147    DONE;
1148  }"
1149)
1150
1151(define_insn "*thumb2_alusi3_short"
1152  [(set (match_operand:SI          0 "s_register_operand" "=l")
1153        (match_operator:SI 3 "thumb_16bit_operator"
1154	 [(match_operand:SI 1 "s_register_operand" "0")
1155	  (match_operand:SI 2 "s_register_operand" "l")]))
1156   (clobber (reg:CC CC_REGNUM))]
1157  "TARGET_THUMB2 && reload_completed
1158   && GET_CODE(operands[3]) != PLUS
1159   && GET_CODE(operands[3]) != MINUS"
1160  "%I3%!\\t%0, %1, %2"
1161  [(set_attr "predicable" "yes")
1162   (set_attr "length" "2")
1163   (set_attr "type" "alu_sreg")]
1164)
1165
1166(define_insn "*thumb2_shiftsi3_short"
1167  [(set (match_operand:SI   0 "low_register_operand" "=l,l")
1168	(match_operator:SI  3 "shift_operator"
1169	 [(match_operand:SI 1 "low_register_operand"  "0,l")
1170	  (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1171   (clobber (reg:CC CC_REGNUM))]
1172  "TARGET_THUMB2 && reload_completed
1173   && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1174       || REG_P (operands[2]))"
1175  "* return arm_output_shift(operands, 2);"
1176  [(set_attr "predicable" "yes")
1177   (set_attr "shift" "1")
1178   (set_attr "length" "2")
1179   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1180		      (const_string "alu_shift_imm")
1181		      (const_string "alu_shift_reg")))]
1182)
1183
1184(define_insn "*thumb2_mov<mode>_shortim"
1185  [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1186	(match_operand:QHSI 1 "const_int_operand" "I"))
1187   (clobber (reg:CC CC_REGNUM))]
1188  "TARGET_THUMB2 && reload_completed"
1189  "mov%!\t%0, %1"
1190  [(set_attr "predicable" "yes")
1191   (set_attr "length" "2")
1192   (set_attr "type" "mov_imm")]
1193)
1194
1195(define_insn "*thumb2_addsi_short"
1196  [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1197	(plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1198		 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1199   (clobber (reg:CC CC_REGNUM))]
1200  "TARGET_THUMB2 && reload_completed"
1201  "*
1202    HOST_WIDE_INT val;
1203
1204    if (CONST_INT_P (operands[2]))
1205      val = INTVAL(operands[2]);
1206    else
1207      val = 0;
1208
1209    /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff.  */
1210    if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1211      return \"sub%!\\t%0, %1, #%n2\";
1212    else
1213      return \"add%!\\t%0, %1, %2\";
1214  "
1215  [(set_attr "predicable" "yes")
1216   (set_attr "length" "2")
1217   (set_attr_alternative "type"
1218                         [(if_then_else (match_operand 2 "const_int_operand" "")
1219                                        (const_string "alu_imm")
1220                                        (const_string "alu_sreg"))
1221                          (const_string "alu_imm")])]
1222)
1223
1224(define_insn "*thumb2_subsi_short"
1225  [(set (match_operand:SI 0 "low_register_operand" "=l")
1226	(minus:SI (match_operand:SI 1 "low_register_operand" "l")
1227		  (match_operand:SI 2 "low_register_operand" "l")))
1228   (clobber (reg:CC CC_REGNUM))]
1229  "TARGET_THUMB2 && reload_completed"
1230  "sub%!\\t%0, %1, %2"
1231  [(set_attr "predicable" "yes")
1232   (set_attr "length" "2")
1233   (set_attr "type" "alu_sreg")]
1234)
1235
1236(define_peephole2
1237  [(set (match_operand:CC 0 "cc_register" "")
1238	(compare:CC (match_operand:SI 1 "low_register_operand" "")
1239		    (match_operand:SI 2 "const_int_operand" "")))]
1240  "TARGET_THUMB2
1241   && peep2_reg_dead_p (1, operands[1])
1242   && satisfies_constraint_Pw (operands[2])"
1243  [(parallel
1244    [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1245     (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1246  "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1247)
1248
1249(define_peephole2
1250  [(match_scratch:SI 3 "l")
1251   (set (match_operand:CC 0 "cc_register" "")
1252	(compare:CC (match_operand:SI 1 "low_register_operand" "")
1253		    (match_operand:SI 2 "const_int_operand" "")))]
1254  "TARGET_THUMB2
1255   && satisfies_constraint_Px (operands[2])"
1256  [(parallel
1257    [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1258     (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1259  "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1260)
1261
1262(define_insn "thumb2_addsi3_compare0"
1263  [(set (reg:CC_NOOV CC_REGNUM)
1264	(compare:CC_NOOV
1265	  (plus:SI (match_operand:SI 1 "s_register_operand" "l,  0, r")
1266		   (match_operand:SI 2 "arm_add_operand"    "lPt,Ps,rIL"))
1267	  (const_int 0)))
1268   (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1269	(plus:SI (match_dup 1) (match_dup 2)))]
1270  "TARGET_THUMB2"
1271  "*
1272    HOST_WIDE_INT val;
1273
1274    if (CONST_INT_P (operands[2]))
1275      val = INTVAL (operands[2]);
1276    else
1277      val = 0;
1278
1279    if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1280      return \"subs\\t%0, %1, #%n2\";
1281    else
1282      return \"adds\\t%0, %1, %2\";
1283  "
1284  [(set_attr "conds" "set")
1285   (set_attr "length" "2,2,4")
1286   (set_attr_alternative "type"
1287                         [(if_then_else (match_operand 2 "const_int_operand" "")
1288                                        (const_string "alus_imm")
1289                                        (const_string "alus_sreg"))
1290                          (const_string "alus_imm")
1291                          (if_then_else (match_operand 2 "const_int_operand" "")
1292                                        (const_string "alus_imm")
1293                                        (const_string "alus_sreg"))])]
1294)
1295
1296(define_insn "*thumb2_addsi3_compare0_scratch"
1297  [(set (reg:CC_NOOV CC_REGNUM)
1298	(compare:CC_NOOV
1299	  (plus:SI (match_operand:SI 0 "s_register_operand" "l,  r")
1300		   (match_operand:SI 1 "arm_add_operand"    "lPv,rIL"))
1301	  (const_int 0)))]
1302  "TARGET_THUMB2"
1303  "*
1304    HOST_WIDE_INT val;
1305
1306    if (CONST_INT_P (operands[1]))
1307      val = INTVAL (operands[1]);
1308    else
1309      val = 0;
1310
1311    if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1312      return \"cmp\\t%0, #%n1\";
1313    else
1314      return \"cmn\\t%0, %1\";
1315  "
1316  [(set_attr "conds" "set")
1317   (set_attr "length" "2,4")
1318   (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1319                                    (const_string "alus_imm")
1320                                    (const_string "alus_sreg")))]
1321)
1322
1323(define_insn "*thumb2_mulsi_short"
1324  [(set (match_operand:SI 0 "low_register_operand" "=l")
1325        (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1326                 (match_operand:SI 2 "low_register_operand" "l")))
1327   (clobber (reg:CC CC_REGNUM))]
1328  "TARGET_THUMB2 && optimize_size && reload_completed"
1329  "mul%!\\t%0, %2, %0"
1330  [(set_attr "predicable" "yes")
1331   (set_attr "length" "2")
1332   (set_attr "type" "muls")])
1333
1334(define_insn "*thumb2_mulsi_short_compare0"
1335  [(set (reg:CC_NOOV CC_REGNUM)
1336        (compare:CC_NOOV
1337         (mult:SI (match_operand:SI 1 "register_operand" "%0")
1338	          (match_operand:SI 2 "register_operand" "l"))
1339         (const_int 0)))
1340   (set (match_operand:SI 0 "register_operand" "=l")
1341	(mult:SI (match_dup 1) (match_dup 2)))]
1342  "TARGET_THUMB2 && optimize_size"
1343  "muls\\t%0, %2, %0"
1344  [(set_attr "length" "2")
1345   (set_attr "type" "muls")])
1346
1347(define_insn "*thumb2_mulsi_short_compare0_scratch"
1348  [(set (reg:CC_NOOV CC_REGNUM)
1349        (compare:CC_NOOV
1350         (mult:SI (match_operand:SI 1 "register_operand" "%0")
1351	          (match_operand:SI 2 "register_operand" "l"))
1352         (const_int 0)))
1353   (clobber (match_scratch:SI 0 "=l"))]
1354  "TARGET_THUMB2 && optimize_size"
1355  "muls\\t%0, %2, %0"
1356  [(set_attr "length" "2")
1357   (set_attr "type" "muls")])
1358
1359(define_insn "*thumb2_cbz"
1360  [(set (pc) (if_then_else
1361	      (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1362		  (const_int 0))
1363	      (label_ref (match_operand 1 "" ""))
1364	      (pc)))
1365   (clobber (reg:CC CC_REGNUM))]
1366  "TARGET_THUMB2"
1367  "*
1368  if (get_attr_length (insn) == 2)
1369    return \"cbz\\t%0, %l1\";
1370  else
1371    return \"cmp\\t%0, #0\;beq\\t%l1\";
1372  "
1373  [(set (attr "length")
1374        (if_then_else
1375	    (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1376	         (le (minus (match_dup 1) (pc)) (const_int 128))
1377	         (not (match_test "which_alternative")))
1378	    (const_int 2)
1379	    (const_int 8)))
1380   (set_attr "type" "branch,multiple")]
1381)
1382
1383(define_insn "*thumb2_cbnz"
1384  [(set (pc) (if_then_else
1385	      (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1386		  (const_int 0))
1387	      (label_ref (match_operand 1 "" ""))
1388	      (pc)))
1389   (clobber (reg:CC CC_REGNUM))]
1390  "TARGET_THUMB2"
1391  "*
1392  if (get_attr_length (insn) == 2)
1393    return \"cbnz\\t%0, %l1\";
1394  else
1395    return \"cmp\\t%0, #0\;bne\\t%l1\";
1396  "
1397  [(set (attr "length")
1398        (if_then_else
1399	    (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1400	         (le (minus (match_dup 1) (pc)) (const_int 128))
1401	         (not (match_test "which_alternative")))
1402	    (const_int 2)
1403	    (const_int 8)))
1404   (set_attr "type" "branch,multiple")]
1405)
1406
1407(define_insn "*thumb2_one_cmplsi2_short"
1408  [(set (match_operand:SI 0 "low_register_operand" "=l")
1409	(not:SI (match_operand:SI 1 "low_register_operand" "l")))
1410   (clobber (reg:CC CC_REGNUM))]
1411  "TARGET_THUMB2 && reload_completed"
1412  "mvn%!\t%0, %1"
1413  [(set_attr "predicable" "yes")
1414   (set_attr "length" "2")
1415   (set_attr "type" "mvn_reg")]
1416)
1417
1418(define_insn "*thumb2_negsi2_short"
1419  [(set (match_operand:SI 0 "low_register_operand" "=l")
1420	(neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1421   (clobber (reg:CC CC_REGNUM))]
1422  "TARGET_THUMB2 && reload_completed"
1423  "rsb%!\t%0, %1, #0"
1424  [(set_attr "predicable" "yes")
1425   (set_attr "length" "2")
1426   (set_attr "type" "alu_sreg")]
1427)
1428
1429; Constants for op 2 will never be given to these patterns.
1430(define_insn_and_split "*iordi_notdi_di"
1431  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1432	(ior:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
1433		(match_operand:DI 2 "s_register_operand" "r,0")))]
1434  "TARGET_THUMB2"
1435  "#"
1436  "TARGET_THUMB2 && reload_completed"
1437  [(set (match_dup 0) (ior:SI (not:SI (match_dup 1)) (match_dup 2)))
1438   (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
1439  "
1440  {
1441    operands[3] = gen_highpart (SImode, operands[0]);
1442    operands[0] = gen_lowpart (SImode, operands[0]);
1443    operands[4] = gen_highpart (SImode, operands[1]);
1444    operands[1] = gen_lowpart (SImode, operands[1]);
1445    operands[5] = gen_highpart (SImode, operands[2]);
1446    operands[2] = gen_lowpart (SImode, operands[2]);
1447  }"
1448  [(set_attr "length" "8")
1449   (set_attr "predicable" "yes")
1450   (set_attr "predicable_short_it" "no")
1451   (set_attr "type" "multiple")]
1452)
1453
1454(define_insn_and_split "*iordi_notzesidi_di"
1455  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1456	(ior:DI (not:DI (zero_extend:DI
1457			 (match_operand:SI 2 "s_register_operand" "r,r")))
1458		(match_operand:DI 1 "s_register_operand" "0,?r")))]
1459  "TARGET_THUMB2"
1460  "#"
1461  ; (not (zero_extend...)) means operand0 will always be 0xffffffff
1462  "TARGET_THUMB2 && reload_completed"
1463  [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1464   (set (match_dup 3) (const_int -1))]
1465  "
1466  {
1467    operands[3] = gen_highpart (SImode, operands[0]);
1468    operands[0] = gen_lowpart (SImode, operands[0]);
1469    operands[1] = gen_lowpart (SImode, operands[1]);
1470  }"
1471  [(set_attr "length" "4,8")
1472   (set_attr "predicable" "yes")
1473   (set_attr "predicable_short_it" "no")
1474   (set_attr "type" "multiple")]
1475)
1476
1477(define_insn_and_split "*iordi_notdi_zesidi"
1478  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1479	(ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "0,?r"))
1480		(zero_extend:DI
1481		 (match_operand:SI 1 "s_register_operand" "r,r"))))]
1482  "TARGET_THUMB2"
1483  "#"
1484  "TARGET_THUMB2 && reload_completed"
1485  [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1486   (set (match_dup 3) (not:SI (match_dup 4)))]
1487  "
1488  {
1489    operands[3] = gen_highpart (SImode, operands[0]);
1490    operands[0] = gen_lowpart (SImode, operands[0]);
1491    operands[1] = gen_lowpart (SImode, operands[1]);
1492    operands[4] = gen_highpart (SImode, operands[2]);
1493    operands[2] = gen_lowpart (SImode, operands[2]);
1494  }"
1495  [(set_attr "length" "8")
1496   (set_attr "predicable" "yes")
1497   (set_attr "predicable_short_it" "no")
1498   (set_attr "type" "multiple")]
1499)
1500
1501(define_insn_and_split "*iordi_notsesidi_di"
1502  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1503	(ior:DI (not:DI (sign_extend:DI
1504			 (match_operand:SI 2 "s_register_operand" "r,r")))
1505		(match_operand:DI 1 "s_register_operand" "0,r")))]
1506  "TARGET_THUMB2"
1507  "#"
1508  "TARGET_THUMB2 && reload_completed"
1509  [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1510   (set (match_dup 3) (ior:SI (not:SI
1511				(ashiftrt:SI (match_dup 2) (const_int 31)))
1512			       (match_dup 4)))]
1513  "
1514  {
1515    operands[3] = gen_highpart (SImode, operands[0]);
1516    operands[0] = gen_lowpart (SImode, operands[0]);
1517    operands[4] = gen_highpart (SImode, operands[1]);
1518    operands[1] = gen_lowpart (SImode, operands[1]);
1519  }"
1520  [(set_attr "length" "8")
1521   (set_attr "predicable" "yes")
1522   (set_attr "predicable_short_it" "no")
1523   (set_attr "type" "multiple")]
1524)
1525
1526(define_insn "*orsi_notsi_si"
1527  [(set (match_operand:SI 0 "s_register_operand" "=r")
1528	(ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1529		(match_operand:SI 1 "s_register_operand" "r")))]
1530  "TARGET_THUMB2"
1531  "orn%?\\t%0, %1, %2"
1532  [(set_attr "predicable" "yes")
1533   (set_attr "type" "logic_reg")]
1534)
1535
1536(define_insn "*orsi_not_shiftsi_si"
1537  [(set (match_operand:SI 0 "s_register_operand" "=r")
1538	(ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1539			 [(match_operand:SI 2 "s_register_operand" "r")
1540			  (match_operand:SI 3 "const_int_operand" "M")]))
1541		(match_operand:SI 1 "s_register_operand" "r")))]
1542  "TARGET_THUMB2"
1543  "orn%?\\t%0, %1, %2%S4"
1544  [(set_attr "predicable" "yes")
1545   (set_attr "shift" "2")
1546   (set_attr "type" "alu_shift_imm")]
1547)
1548
1549(define_peephole2
1550  [(set (match_operand:CC_NOOV 0 "cc_register" "")
1551	(compare:CC_NOOV (zero_extract:SI
1552			  (match_operand:SI 1 "low_register_operand" "")
1553			  (const_int 1)
1554			  (match_operand:SI 2 "const_int_operand" ""))
1555			 (const_int 0)))
1556   (match_scratch:SI 3 "l")
1557   (set (pc)
1558	(if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1559		       [(match_dup 0) (const_int 0)])
1560		      (match_operand 5 "" "")
1561		      (match_operand 6 "" "")))]
1562  "TARGET_THUMB2
1563   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1564   && peep2_reg_dead_p (2, operands[0])"
1565  [(parallel [(set (match_dup 0)
1566		   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1567				    (const_int 0)))
1568	      (clobber (match_dup 3))])
1569   (set (pc)
1570	(if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1571		      (match_dup 5) (match_dup 6)))]
1572  "
1573  operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1574  operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1575				VOIDmode, operands[0], const0_rtx);
1576  ")
1577
1578(define_peephole2
1579  [(set (match_operand:CC_NOOV 0 "cc_register" "")
1580	(compare:CC_NOOV (zero_extract:SI
1581			  (match_operand:SI 1 "low_register_operand" "")
1582			  (match_operand:SI 2 "const_int_operand" "")
1583			  (const_int 0))
1584			 (const_int 0)))
1585   (match_scratch:SI 3 "l")
1586   (set (pc)
1587	(if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1588		       [(match_dup 0) (const_int 0)])
1589		      (match_operand 5 "" "")
1590		      (match_operand 6 "" "")))]
1591  "TARGET_THUMB2
1592   && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1593   && peep2_reg_dead_p (2, operands[0])"
1594  [(parallel [(set (match_dup 0)
1595		   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1596				    (const_int 0)))
1597	      (clobber (match_dup 3))])
1598   (set (pc)
1599	(if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1600		      (match_dup 5) (match_dup 6)))]
1601  "
1602  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1603  ")
1604
1605;; Define the subtract-one-and-jump insns so loop.c
1606;; knows what to generate.
1607(define_expand "doloop_end"
1608  [(use (match_operand 0 "" ""))      ; loop pseudo
1609   (use (match_operand 1 "" ""))]     ; label
1610  "TARGET_32BIT"
1611  "
1612 {
1613   /* Currently SMS relies on the do-loop pattern to recognize loops
1614      where (1) the control part consists of all insns defining and/or
1615      using a certain 'count' register and (2) the loop count can be
1616      adjusted by modifying this register prior to the loop.
1617      ??? The possible introduction of a new block to initialize the
1618      new IV can potentially affect branch optimizations.  */
1619   if (optimize > 0 && flag_modulo_sched)
1620   {
1621     rtx s0;
1622     rtx bcomp;
1623     rtx loc_ref;
1624     rtx cc_reg;
1625     rtx insn;
1626     rtx cmp;
1627
1628     if (GET_MODE (operands[0]) != SImode)
1629       FAIL;
1630
1631     s0 = operands [0];
1632     if (TARGET_THUMB2)
1633       insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1634     else
1635       insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1636
1637     cmp = XVECEXP (PATTERN (insn), 0, 0);
1638     cc_reg = SET_DEST (cmp);
1639     bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1640     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1641     emit_jump_insn (gen_rtx_SET (pc_rtx,
1642                                  gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1643                                                        loc_ref, pc_rtx)));
1644     DONE;
1645   }else
1646      FAIL;
1647 }")
1648
1649