* gimplify.c (nonlocal_vlas): Delete.
[official-gcc.git] / gcc / config / arm / thumb2.md
blobc42670f8643c3286bc5abf537d4fd0483cba68ac
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.
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.  */
21 ;; Note: Thumb-2 is the variant of the Thumb architecture that adds
22 ;; 32-bit encodings of [almost all of] the Arm instruction set.
23 ;; Some old documents refer to the relatively minor interworking
24 ;; changes made in armv5t as "thumb2".  These are considered part
25 ;; the 16-bit Thumb-1 instruction set.
27 ;; 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")]
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")]
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")]
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")]
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")]
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);
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")]
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);
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")]
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")]
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,*,*")]
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")]
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")]
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")]
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")]
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")]
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")]
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]);
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);
401   }
402   [(set_attr "conds" "use")
403    (set_attr "length" "8")
404    (set_attr "type" "multiple")]
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")]
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")]
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;
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);
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")])]
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")]
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")]
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")]
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")]
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")]
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")]
599 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
600 ;; addresses will have the thumb bit set correctly.
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]);
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)))]
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]);
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")]
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]);
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")]
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")]
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\";
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")]
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;
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       }
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])));
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")]
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")]
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);
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]));
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);
925        emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
926                                                         operands[2])));
928        emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
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")]
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     }
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")]
1029 ;; Zero and sign extension instructions.
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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   }"
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")]
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")))]
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")]
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;
1204     if (CONST_INT_P (operands[2]))
1205       val = INTVAL(operands[2]);
1206     else
1207       val = 0;
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")])]
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")]
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]));"
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]));"
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;
1274     if (CONST_INT_P (operands[2]))
1275       val = INTVAL (operands[2]);
1276     else
1277       val = 0;
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"))])]
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;
1306     if (CONST_INT_P (operands[1]))
1307       val = INTVAL (operands[1]);
1308     else
1309       val = 0;
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")))]
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")])
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")])
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")])
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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")]
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   ")
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   ")
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   "
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;
1628      if (GET_MODE (operands[0]) != SImode)
1629        FAIL;
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)));
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  }")