Adjust literal pool offset in Thumb-2 movsi patterns
[official-gcc.git] / gcc / config / arm / thumb2.md
blob608ea70a5d09ba5231f774e974ea7c6cddeb51b3
1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2019 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,lk*r,m")
251         (match_operand:SI 1 "general_operand"      "rk,I,Py,K,j,mi,lk*r"))]
252   "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
253    && (   register_operand (operands[0], SImode)
254        || register_operand (operands[1], SImode))"
256   switch (which_alternative)
257     {
258     case 0:
259     case 1:
260     case 2:
261       return \"mov%?\\t%0, %1\";
262     case 3: return \"mvn%?\\t%0, #%B1\";
263     case 4: return \"movw%?\\t%0, %1\";
264     case 5:
265       /* Cannot load it directly, split to load it via MOV / MOVT.  */
266       if (!MEM_P (operands[1]) && arm_disable_literal_pool)
267         return \"#\";
268       return \"ldr%?\\t%0, %1\";
269     case 6: return \"str%?\\t%1, %0\";
270     default: gcc_unreachable ();
271     }
273   [(set_attr "type" "mov_reg,mov_imm,mov_imm,mvn_imm,mov_imm,load_4,store_4")
274    (set_attr "length" "2,4,2,4,4,4,4")
275    (set_attr "predicable" "yes")
276    (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no")
277    (set_attr "pool_range" "*,*,*,*,*,1018,*")
278    (set_attr "neg_pool_range" "*,*,*,*,*,0,*")]
281 (define_insn "tls_load_dot_plus_four"
282   [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
283         (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
284                             (const_int 4)
285                             (match_operand 3 "" "")]
286                            UNSPEC_PIC_BASE)))
287    (clobber (match_scratch:SI 1 "=X,l,X,r"))]
288   "TARGET_THUMB2"
289   "*
290   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
291                              INTVAL (operands[3]));
292   return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
293   "
294   [(set_attr "length" "4,4,6,6")
295    (set_attr "type" "multiple")]
298 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
299 ;; of the messiness associated with the ARM patterns.
300 (define_insn "*thumb2_movhi_insn"
301   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,l,r,m,r")
302         (match_operand:HI 1 "general_operand"      "rk,I,Py,n,r,m"))]
303   "TARGET_THUMB2
304   && (register_operand (operands[0], HImode)
305      || register_operand (operands[1], HImode))"
306   "@
307    mov%?\\t%0, %1\\t%@ movhi
308    mov%?\\t%0, %1\\t%@ movhi
309    mov%?\\t%0, %1\\t%@ movhi
310    movw%?\\t%0, %L1\\t%@ movhi
311    strh%?\\t%1, %0\\t%@ movhi
312    ldrh%?\\t%0, %1\\t%@ movhi"
313   [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store_4,load_4")
314    (set_attr "predicable" "yes")
315    (set_attr "predicable_short_it" "yes,no,yes,no,no,no")
316    (set_attr "length" "2,4,2,4,4,4")
317    (set_attr "pool_range" "*,*,*,*,*,4094")
318    (set_attr "neg_pool_range" "*,*,*,*,*,250")]
321 (define_insn "*thumb2_storewb_pairsi"
322   [(set (match_operand:SI 0 "register_operand" "=&kr")
323         (plus:SI (match_operand:SI 1 "register_operand" "0")
324                  (match_operand:SI 2 "const_int_operand" "n")))
325    (set (mem:SI (plus:SI (match_dup 0) (match_dup 2)))
326         (match_operand:SI 3 "register_operand" "r"))
327    (set (mem:SI (plus:SI (match_dup 0)
328                          (match_operand:SI 5 "const_int_operand" "n")))
329         (match_operand:SI 4 "register_operand" "r"))]
330   "TARGET_THUMB2
331    && INTVAL (operands[5]) == INTVAL (operands[2]) + 4"
332   "strd\\t%3, %4, [%0, %2]!"
333   [(set_attr "type" "store_8")]
336 (define_insn "*thumb2_cmpsi_neg_shiftsi"
337   [(set (reg:CC CC_REGNUM)
338         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
339                     (neg:SI (match_operator:SI 3 "shift_operator"
340                              [(match_operand:SI 1 "s_register_operand" "r")
341                               (match_operand:SI 2 "const_int_operand" "M")]))))]
342   "TARGET_THUMB2"
343   "cmn%?\\t%0, %1%S3"
344   [(set_attr "conds" "set")
345    (set_attr "shift" "1")
346    (set_attr "type" "alus_shift_imm")]
349 (define_insn_and_split "*thumb2_mov_scc"
350   [(set (match_operand:SI 0 "s_register_operand" "=l,r")
351         (match_operator:SI 1 "arm_comparison_operator_mode"
352          [(match_operand 2 "cc_register" "") (const_int 0)]))]
353   "TARGET_THUMB2"
354   "#"   ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
355   "TARGET_THUMB2"
356   [(set (match_dup 0)
357         (if_then_else:SI (match_dup 1)
358                          (const_int 1)
359                          (const_int 0)))]
360   ""
361   [(set_attr "conds" "use")
362    (set_attr "enabled_for_short_it" "yes,no")
363    (set_attr "length" "8,10")
364    (set_attr "type" "multiple")]
367 (define_insn_and_split "*thumb2_mov_negscc"
368   [(set (match_operand:SI 0 "s_register_operand" "=r")
369         (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
370                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
371   "TARGET_THUMB2 && !arm_restrict_it"
372   "#"   ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
373   "&& true"
374   [(set (match_dup 0)
375         (if_then_else:SI (match_dup 1)
376                          (match_dup 3)
377                          (const_int 0)))]
378   {
379     operands[3] = GEN_INT (~0);
380   }
381   [(set_attr "conds" "use")
382    (set_attr "length" "10")
383    (set_attr "type" "multiple")]
386 (define_insn_and_split "*thumb2_mov_negscc_strict_it"
387   [(set (match_operand:SI 0 "low_register_operand" "=l")
388         (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
389                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
390   "TARGET_THUMB2 && arm_restrict_it"
391   "#"   ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\"
392   "&& reload_completed"
393   [(set (match_dup 0)
394         (match_dup 3))
395    (cond_exec (match_dup 4)
396               (set (match_dup 0)
397                    (const_int 0)))]
398   {
399     operands[3] = GEN_INT (~0);
400     machine_mode mode = GET_MODE (operands[2]);
401     enum rtx_code rc = GET_CODE (operands[1]);
403     if (mode == CCFPmode || mode == CCFPEmode)
404       rc = reverse_condition_maybe_unordered (rc);
405     else
406       rc = reverse_condition (rc);
407     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
409   }
410   [(set_attr "conds" "use")
411    (set_attr "length" "8")
412    (set_attr "type" "multiple")]
415 (define_insn_and_split "*thumb2_mov_notscc"
416   [(set (match_operand:SI 0 "s_register_operand" "=r")
417         (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
418                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
419   "TARGET_THUMB2 && !arm_restrict_it"
420   "#"   ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
421   "&& true"
422   [(set (match_dup 0)
423         (if_then_else:SI (match_dup 1)
424                          (match_dup 3)
425                          (match_dup 4)))]
426   {
427     operands[3] = GEN_INT (~1);
428     operands[4] = GEN_INT (~0);
429   }
430   [(set_attr "conds" "use")
431    (set_attr "length" "10")
432    (set_attr "type" "multiple")]
435 (define_insn_and_split "*thumb2_mov_notscc_strict_it"
436   [(set (match_operand:SI 0 "low_register_operand" "=l")
437         (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
438                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
439   "TARGET_THUMB2 && arm_restrict_it"
440   "#"   ; "mvn %0, #0 ; it%d1 ; lsl%d1 %0, %0, #1"
441   "&& reload_completed"
442   [(set (match_dup 0)
443         (match_dup 3))
444    (cond_exec (match_dup 4)
445               (set (match_dup 0)
446                    (ashift:SI (match_dup 0)
447                               (const_int 1))))]
448   {
449     operands[3] = GEN_INT (~0);
450     operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
451                                   VOIDmode, operands[2], const0_rtx);
452   }
453   [(set_attr "conds" "use")
454    (set_attr "length" "8")
455    (set_attr "type" "multiple")]
458 (define_insn_and_split "*thumb2_movsicc_insn"
459   [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r")
460         (if_then_else:SI
461          (match_operator 3 "arm_comparison_operator"
462           [(match_operand 4 "cc_register" "") (const_int 0)])
463          (match_operand:SI 1 "arm_not_operand" "0 ,lPy,0 ,0,rI,K,I ,r,rI,K ,K,r")
464          (match_operand:SI 2 "arm_not_operand" "lPy,0 ,rI,K,0 ,0,rI,I,K ,rI,K,r")))]
465   "TARGET_THUMB2"
466   "@
467    it\\t%D3\;mov%D3\\t%0, %2
468    it\\t%d3\;mov%d3\\t%0, %1
469    it\\t%D3\;mov%D3\\t%0, %2
470    it\\t%D3\;mvn%D3\\t%0, #%B2
471    it\\t%d3\;mov%d3\\t%0, %1
472    it\\t%d3\;mvn%d3\\t%0, #%B1
473    #
474    #
475    #
476    #
477    #
478    #"
479    ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
480    ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
481    ; alt 8: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
482    ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
483    ; alt 10: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
484    ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
485   "&& reload_completed"
486   [(const_int 0)]
487   {
488     enum rtx_code rev_code;
489     machine_mode mode;
490     rtx rev_cond;
492     emit_insn (gen_rtx_COND_EXEC (VOIDmode,
493                                   operands[3],
494                                   gen_rtx_SET (operands[0], operands[1])));
495     rev_code = GET_CODE (operands[3]);
496     mode = GET_MODE (operands[4]);
497     if (mode == CCFPmode || mode == CCFPEmode)
498       rev_code = reverse_condition_maybe_unordered (rev_code);
499     else
500       rev_code = reverse_condition (rev_code);
502     rev_cond = gen_rtx_fmt_ee (rev_code,
503                                VOIDmode,
504                                gen_rtx_REG (mode, CC_REGNUM),
505                                const0_rtx);
506     emit_insn (gen_rtx_COND_EXEC (VOIDmode,
507                                   rev_cond,
508                                   gen_rtx_SET (operands[0], operands[2])));
509     DONE;
510   }
511   [(set_attr "length" "4,4,6,6,6,6,10,8,10,10,10,6")
512    (set_attr "enabled_for_short_it" "yes,yes,no,no,no,no,no,no,no,no,no,yes")
513    (set_attr "conds" "use")
514    (set_attr_alternative "type"
515                          [(if_then_else (match_operand 2 "const_int_operand" "")
516                                         (const_string "mov_imm")
517                                         (const_string "mov_reg"))
518                           (if_then_else (match_operand 1 "const_int_operand" "")
519                                         (const_string "mov_imm")
520                                         (const_string "mov_reg"))
521                           (if_then_else (match_operand 2 "const_int_operand" "")
522                                         (const_string "mov_imm")
523                                         (const_string "mov_reg"))
524                           (const_string "mvn_imm")
525                           (if_then_else (match_operand 1 "const_int_operand" "")
526                                         (const_string "mov_imm")
527                                         (const_string "mov_reg"))
528                           (const_string "mvn_imm")
529                           (const_string "multiple")
530                           (const_string "multiple")
531                           (const_string "multiple")
532                           (const_string "multiple")
533                           (const_string "multiple")
534                           (const_string "multiple")])]
537 (define_insn "*thumb2_movsfcc_soft_insn"
538   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
539         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
540                           [(match_operand 4 "cc_register" "") (const_int 0)])
541                          (match_operand:SF 1 "s_register_operand" "0,r")
542                          (match_operand:SF 2 "s_register_operand" "r,0")))]
543   "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
544   "@
545    it\\t%D3\;mov%D3\\t%0, %2
546    it\\t%d3\;mov%d3\\t%0, %1"
547   [(set_attr "length" "6,6")
548    (set_attr "conds" "use")
549    (set_attr "type" "multiple")]
552 (define_insn "*call_reg_thumb2"
553   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
554          (match_operand 1 "" ""))
555    (use (match_operand 2 "" ""))
556    (clobber (reg:SI LR_REGNUM))]
557   "TARGET_THUMB2"
558   "blx%?\\t%0"
559   [(set_attr "type" "call")]
562 (define_insn "*nonsecure_call_reg_thumb2"
563   [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
564                     UNSPEC_NONSECURE_MEM)
565          (match_operand 0 "" ""))
566    (use (match_operand 1 "" ""))
567    (clobber (reg:SI LR_REGNUM))]
568   "TARGET_THUMB2 && use_cmse"
569   "bl\\t__gnu_cmse_nonsecure_call"
570   [(set_attr "length" "4")
571    (set_attr "type" "call")]
574 (define_insn "*call_value_reg_thumb2"
575   [(set (match_operand 0 "" "")
576         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
577               (match_operand 2 "" "")))
578    (use (match_operand 3 "" ""))
579    (clobber (reg:SI LR_REGNUM))]
580   "TARGET_THUMB2"
581   "blx\\t%1"
582   [(set_attr "type" "call")]
585 (define_insn "*nonsecure_call_value_reg_thumb2"
586   [(set (match_operand 0 "" "")
587         (call
588          (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
589                     UNSPEC_NONSECURE_MEM)
590          (match_operand 1 "" "")))
591    (use (match_operand 2 "" ""))
592    (clobber (reg:SI LR_REGNUM))]
593   "TARGET_THUMB2 && use_cmse"
594   "bl\t__gnu_cmse_nonsecure_call"
595   [(set_attr "length" "4")
596    (set_attr "type" "call")]
599 (define_insn "*thumb2_indirect_jump"
600   [(set (pc)
601         (match_operand:SI 0 "register_operand" "l*r"))]
602   "TARGET_THUMB2"
603   "bx\\t%0"
604   [(set_attr "conds" "clob")
605    (set_attr "type" "branch")]
607 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
608 ;; addresses will have the thumb bit set correctly.
611 (define_insn_and_split "*thumb2_and_scc"
612   [(set (match_operand:SI 0 "s_register_operand" "=Ts")
613         (and:SI (match_operator:SI 1 "arm_comparison_operator"
614                  [(match_operand 2 "cc_register" "") (const_int 0)])
615                 (match_operand:SI 3 "s_register_operand" "r")))]
616   "TARGET_THUMB2"
617   "#"   ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
618   "&& reload_completed"
619   [(set (match_dup 0)
620         (and:SI (match_dup 3) (const_int 1)))
621    (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
622   {
623     machine_mode mode = GET_MODE (operands[2]);
624     enum rtx_code rc = GET_CODE (operands[1]);
626     if (mode == CCFPmode || mode == CCFPEmode)
627       rc = reverse_condition_maybe_unordered (rc);
628     else
629       rc = reverse_condition (rc);
630     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
631   }
632   [(set_attr "conds" "use")
633    (set_attr "type" "multiple")
634    (set (attr "length") (if_then_else (match_test "arm_restrict_it")
635                                       (const_int 8)
636                                       (const_int 10)))]
639 (define_insn_and_split "*thumb2_ior_scc"
640   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
641         (ior:SI (match_operator:SI 1 "arm_comparison_operator"
642                  [(match_operand 2 "cc_register" "") (const_int 0)])
643                 (match_operand:SI 3 "s_register_operand" "0,?r")))]
644   "TARGET_THUMB2 && !arm_restrict_it"
645   "@
646    it\\t%d1\;orr%d1\\t%0, %3, #1
647    #"
648    ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
649    "&& reload_completed
650     && REGNO (operands [0]) != REGNO (operands[3])"
651    [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
652     (cond_exec (match_dup 4) (set (match_dup 0)
653                                   (ior:SI (match_dup 3) (const_int 1))))]
654   {
655     machine_mode mode = GET_MODE (operands[2]);
656     enum rtx_code rc = GET_CODE (operands[1]);
658     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
659     if (mode == CCFPmode || mode == CCFPEmode)
660       rc = reverse_condition_maybe_unordered (rc);
661     else
662       rc = reverse_condition (rc);
663     operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
664   }
665   [(set_attr "conds" "use")
666    (set_attr "length" "6,10")
667    (set_attr "type" "multiple")]
670 (define_insn_and_split "*thumb2_ior_scc_strict_it"
671   [(set (match_operand:SI 0 "s_register_operand" "=&r")
672         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
673                  [(match_operand 3 "cc_register" "") (const_int 0)])
674                 (match_operand:SI 1 "s_register_operand" "r")))]
675   "TARGET_THUMB2 && arm_restrict_it"
676   "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
677   "&& reload_completed"
678   [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
679    (cond_exec (match_dup 4)
680      (set (match_dup 0) (match_dup 1)))]
681   {
682     machine_mode mode = GET_MODE (operands[3]);
683     rtx_code rc = GET_CODE (operands[2]);
685     if (mode == CCFPmode || mode == CCFPEmode)
686       rc = reverse_condition_maybe_unordered (rc);
687     else
688       rc = reverse_condition (rc);
689     operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
690   }
691   [(set_attr "conds" "use")
692    (set_attr "length" "8")
693    (set_attr "type" "multiple")]
696 (define_insn "*thumb2_cond_move"
697   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
698         (if_then_else:SI (match_operator 3 "equality_operator"
699                           [(match_operator 4 "arm_comparison_operator"
700                             [(match_operand 5 "cc_register" "") (const_int 0)])
701                            (const_int 0)])
702                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
703                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
704   "TARGET_THUMB2"
705   "*
706     if (GET_CODE (operands[3]) == NE)
707       {
708         if (which_alternative != 1)
709           output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
710         if (which_alternative != 0)
711           output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
712         return \"\";
713       }
714     switch (which_alternative)
715       {
716       case 0:
717         output_asm_insn (\"it\\t%d4\", operands);
718         break;
719       case 1:
720         output_asm_insn (\"it\\t%D4\", operands);
721         break;
722       case 2:
723         if (arm_restrict_it)
724           output_asm_insn (\"it\\t%D4\", operands);
725         else
726           output_asm_insn (\"ite\\t%D4\", operands);
727         break;
728       default:
729         abort();
730       }
731     if (which_alternative != 0)
732       {
733         output_asm_insn (\"mov%D4\\t%0, %1\", operands);
734         if (arm_restrict_it && which_alternative == 2)
735           output_asm_insn (\"it\\t%d4\", operands);
736       }
737     if (which_alternative != 1)
738       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
739     return \"\";
740   "
741   [(set_attr "conds" "use")
742    (set_attr "length" "6,6,10")
743    (set_attr "type" "multiple")]
746 (define_insn "*thumb2_cond_arith"
747   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
748         (match_operator:SI 5 "shiftable_operator"
749          [(match_operator:SI 4 "arm_comparison_operator"
750            [(match_operand:SI 2 "s_register_operand" "r,r")
751             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
752           (match_operand:SI 1 "s_register_operand" "0,?r")]))
753    (clobber (reg:CC CC_REGNUM))]
754   "TARGET_THUMB2 && !arm_restrict_it"
755   "*
756     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
757       return \"%i5\\t%0, %1, %2, lsr #31\";
759     output_asm_insn (\"cmp\\t%2, %3\", operands);
760     if (GET_CODE (operands[5]) == AND)
761       {
762         output_asm_insn (\"ite\\t%D4\", operands);
763         output_asm_insn (\"mov%D4\\t%0, #0\", operands);
764       }
765     else if (GET_CODE (operands[5]) == MINUS)
766       {
767         output_asm_insn (\"ite\\t%D4\", operands);
768         output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
769       }
770     else if (which_alternative != 0)
771       {
772         output_asm_insn (\"ite\\t%D4\", operands);
773         output_asm_insn (\"mov%D4\\t%0, %1\", operands);
774       }
775     else
776       output_asm_insn (\"it\\t%d4\", operands);
777     return \"%i5%d4\\t%0, %1, #1\";
778   "
779   [(set_attr "conds" "clob")
780    (set_attr "length" "14")
781    (set_attr "type" "multiple")]
784 (define_insn_and_split "*thumb2_cond_arith_strict_it"
785   [(set (match_operand:SI 0 "s_register_operand" "=l")
786         (match_operator:SI 5 "shiftable_operator_strict_it"
787          [(match_operator:SI 4 "arm_comparison_operator"
788            [(match_operand:SI 2 "s_register_operand" "r")
789             (match_operand:SI 3 "arm_rhs_operand" "rI")])
790           (match_operand:SI 1 "s_register_operand" "0")]))
791    (clobber (reg:CC CC_REGNUM))]
792   "TARGET_THUMB2 && arm_restrict_it"
793   "#"
794   "&& reload_completed"
795   [(const_int 0)]
796   {
797     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
798       {
799         /*  %i5 %0, %1, %2, lsr #31  */
800         rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
801         rtx op = NULL_RTX;
803         switch (GET_CODE (operands[5]))
804           {
805           case AND:
806             op = gen_rtx_AND (SImode, shifted_op, operands[1]);
807             break;
808            case PLUS:
809             op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
810             break;
811           default: gcc_unreachable ();
812           }
813         emit_insn (gen_rtx_SET (operands[0], op));
814         DONE;
815       }
817     /*  "cmp  %2, %3"  */
818     emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
819                             gen_rtx_COMPARE (CCmode, operands[2],
820                                              operands[3])));
822     if (GET_CODE (operands[5]) == AND)
823       {
824         /*  %i5  %0, %1, #1
825             it%D4
826             mov%D4  %0, #0  */
827         enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
828         emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
829                                                           GEN_INT (1))));
830         emit_insn (gen_rtx_COND_EXEC (VOIDmode,
831                                       gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
832                                       gen_rtx_SET (operands[0], const0_rtx)));
833         DONE;
834       }
835     else
836       {
837         /*  it\\t%d4
838             %i5%d4\\t%0, %1, #1   */
839         emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
840                                                                 VOIDmode,
841                                                                 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
842                                                 gen_rtx_SET (operands[0],
843                                                             gen_rtx_PLUS (SImode,
844                                                                           operands[1],
845                                                                           GEN_INT (1)))));
846         DONE;
847       }
848      FAIL;
849   }
850   [(set_attr "conds" "clob")
851    (set_attr "length" "12")
852    (set_attr "type" "multiple")]
855 (define_insn "*thumb2_cond_sub"
856   [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
857         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
858                   (match_operator:SI 4 "arm_comparison_operator"
859                    [(match_operand:SI 2 "s_register_operand" "r,r")
860                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_THUMB2"
863   "*
864     output_asm_insn (\"cmp\\t%2, %3\", operands);
865     if (which_alternative != 0)
866       {
867         if (arm_restrict_it)
868           {
869             output_asm_insn (\"mov\\t%0, %1\", operands);
870             output_asm_insn (\"it\\t%d4\", operands);
871           }
872         else
873         {
874           output_asm_insn (\"ite\\t%D4\", operands);
875           output_asm_insn (\"mov%D4\\t%0, %1\", operands);
876         }
877       }
878     else
879       output_asm_insn (\"it\\t%d4\", operands);
880     return \"sub%d4\\t%0, %1, #1\";
881   "
882   [(set_attr "conds" "clob")
883    (set_attr "length" "10,14")
884    (set_attr "type" "multiple")]
887 (define_insn_and_split "*thumb2_negscc"
888   [(set (match_operand:SI 0 "s_register_operand" "=Ts")
889         (neg:SI (match_operator 3 "arm_comparison_operator"
890                  [(match_operand:SI 1 "s_register_operand" "r")
891                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_THUMB2"
894   "#"
895   "&& reload_completed"
896   [(const_int 0)]
897   {
898     rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
900     if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
901       {
902         /* Emit asr\\t%0, %1, #31 */
903         emit_insn (gen_rtx_SET (operands[0],
904                                 gen_rtx_ASHIFTRT (SImode,
905                                                   operands[1],
906                                                   GEN_INT (31))));
907         DONE;
908       }
909     else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
910       {
911         /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
912         if (CONST_INT_P (operands[2]))
913           emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
914                                         gen_int_mode (-INTVAL (operands[2]),
915                                                       SImode)));
916         else
917           emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
919         emit_insn (gen_rtx_COND_EXEC (VOIDmode,
920                                       gen_rtx_NE (SImode,
921                                                   cc_reg,
922                                                   const0_rtx),
923                                       gen_rtx_SET (operands[0],
924                                                    GEN_INT (~0))));
925         DONE;
926       }
927     else
928       {
929        /* Emit:  cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
930        enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
931        machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
932        rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
934        emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
935                                                         operands[2])));
937        emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
939        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
940                                      gen_rtx_fmt_ee (rc,
941                                                      VOIDmode,
942                                                      tmp1,
943                                                      const0_rtx),
944                                      gen_rtx_SET (operands[0], const0_rtx)));
945        DONE;
946       }
947     FAIL;
948   }
949   [(set_attr "conds" "clob")
950    (set_attr "length" "14")
951    (set_attr "type" "multiple")]
954 (define_insn "*thumb2_movcond"
955   [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
956         (if_then_else:SI
957          (match_operator 5 "arm_comparison_operator"
958           [(match_operand:SI 3 "s_register_operand" "r,r,r")
959            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
960          (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
961          (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
962    (clobber (reg:CC CC_REGNUM))]
963   "TARGET_THUMB2"
964   "*
965   if (GET_CODE (operands[5]) == LT
966       && (operands[4] == const0_rtx))
967     {
968       if (which_alternative != 1 && REG_P (operands[1]))
969         {
970           if (operands[2] == const0_rtx)
971             return \"and\\t%0, %1, %3, asr #31\";
972           return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
973         }
974       else if (which_alternative != 0 && REG_P (operands[2]))
975         {
976           if (operands[1] == const0_rtx)
977             return \"bic\\t%0, %2, %3, asr #31\";
978           return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
979         }
980       /* The only case that falls through to here is when both ops 1 & 2
981          are constants.  */
982     }
984   if (GET_CODE (operands[5]) == GE
985       && (operands[4] == const0_rtx))
986     {
987       if (which_alternative != 1 && REG_P (operands[1]))
988         {
989           if (operands[2] == const0_rtx)
990             return \"bic\\t%0, %1, %3, asr #31\";
991           return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
992         }
993       else if (which_alternative != 0 && REG_P (operands[2]))
994         {
995           if (operands[1] == const0_rtx)
996             return \"and\\t%0, %2, %3, asr #31\";
997           return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
998         }
999       /* The only case that falls through to here is when both ops 1 & 2
1000          are constants.  */
1001     }
1002   if (CONST_INT_P (operands[4])
1003       && !const_ok_for_arm (INTVAL (operands[4])))
1004     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
1005   else
1006     output_asm_insn (\"cmp\\t%3, %4\", operands);
1007   switch (which_alternative)
1008     {
1009     case 0:
1010       output_asm_insn (\"it\\t%D5\", operands);
1011       break;
1012     case 1:
1013       output_asm_insn (\"it\\t%d5\", operands);
1014       break;
1015     case 2:
1016       if (arm_restrict_it)
1017         {
1018           output_asm_insn (\"mov\\t%0, %1\", operands);
1019           output_asm_insn (\"it\\t%D5\", operands);
1020         }
1021       else
1022         output_asm_insn (\"ite\\t%d5\", operands);
1023       break;
1024     default:
1025       abort();
1026     }
1027   if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1028     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1029   if (which_alternative != 1)
1030     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1031   return \"\";
1032   "
1033   [(set_attr "conds" "clob")
1034    (set_attr "length" "10,10,14")
1035    (set_attr "type" "multiple")]
1038 ;; Zero and sign extension instructions.
1040 ;; All supported Thumb2 implementations are armv6, so only that case is
1041 ;; provided.
1042 (define_insn "*thumb2_extendqisi_v6"
1043   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1044         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1045   "TARGET_THUMB2 && arm_arch6"
1046   "@
1047    sxtb%?\\t%0, %1
1048    ldrsb%?\\t%0, %1"
1049   [(set_attr "type" "extend,load_byte")
1050    (set_attr "predicable" "yes")
1051    (set_attr "pool_range" "*,4094")
1052    (set_attr "neg_pool_range" "*,250")]
1055 (define_insn "*thumb2_zero_extendhisi2_v6"
1056   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1057         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1058   "TARGET_THUMB2 && arm_arch6"
1059   "@
1060    uxth%?\\t%0, %1
1061    ldrh%?\\t%0, %1"
1062   [(set_attr "type" "extend,load_byte")
1063    (set_attr "predicable" "yes")
1064    (set_attr "pool_range" "*,4094")
1065    (set_attr "neg_pool_range" "*,250")]
1068 (define_insn "thumb2_zero_extendqisi2_v6"
1069   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1070         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1071   "TARGET_THUMB2 && arm_arch6"
1072   "@
1073    uxtb%?\\t%0, %1
1074    ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1075   [(set_attr "type" "extend,load_byte")
1076    (set_attr "predicable" "yes")
1077    (set_attr "pool_range" "*,4094")
1078    (set_attr "neg_pool_range" "*,250")]
1081 (define_expand "thumb2_casesi_internal"
1082   [(parallel [(set (pc)
1083                (if_then_else
1084                 (leu (match_operand:SI 0 "s_register_operand")
1085                      (match_operand:SI 1 "arm_rhs_operand"))
1086                 (match_dup 4)
1087                 (label_ref:SI (match_operand 3 ""))))
1088               (clobber (reg:CC CC_REGNUM))
1089               (clobber (match_scratch:SI 5))
1090               (use (label_ref:SI (match_operand 2 "")))])]
1091   "TARGET_THUMB2 && !flag_pic"
1093   operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1094   operands[4] = gen_rtx_PLUS (SImode, operands[4],
1095                               gen_rtx_LABEL_REF (SImode, operands[2]));
1096   operands[4] = gen_rtx_MEM (SImode, operands[4]);
1097   MEM_READONLY_P (operands[4]) = 1;
1098   MEM_NOTRAP_P (operands[4]) = 1;
1101 (define_insn "*thumb2_casesi_internal"
1102   [(parallel [(set (pc)
1103                (if_then_else
1104                 (leu (match_operand:SI 0 "s_register_operand" "r")
1105                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
1106                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1107                                  (label_ref:SI (match_operand 2 "" ""))))
1108                 (label_ref:SI (match_operand 3 "" ""))))
1109               (clobber (reg:CC CC_REGNUM))
1110               (clobber (match_scratch:SI 4 "=&r"))
1111               (use (label_ref:SI (match_dup 2)))])]
1112   "TARGET_THUMB2 && !flag_pic"
1113   "* return thumb2_output_casesi(operands);"
1114   [(set_attr "conds" "clob")
1115    (set_attr "length" "16")
1116    (set_attr "type" "multiple")]
1119 (define_expand "thumb2_casesi_internal_pic"
1120   [(parallel [(set (pc)
1121                (if_then_else
1122                 (leu (match_operand:SI 0 "s_register_operand")
1123                      (match_operand:SI 1 "arm_rhs_operand"))
1124                 (match_dup 4)
1125                 (label_ref:SI (match_operand 3 ""))))
1126               (clobber (reg:CC CC_REGNUM))
1127               (clobber (match_scratch:SI 5))
1128               (clobber (match_scratch:SI 6))
1129               (use (label_ref:SI (match_operand 2 "")))])]
1130   "TARGET_THUMB2 && flag_pic"
1132   operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1133   operands[4] = gen_rtx_PLUS (SImode, operands[4],
1134                               gen_rtx_LABEL_REF (SImode, operands[2]));
1135   operands[4] = gen_rtx_MEM (SImode, operands[4]);
1136   MEM_READONLY_P (operands[4]) = 1;
1137   MEM_NOTRAP_P (operands[4]) = 1;
1140 (define_insn "*thumb2_casesi_internal_pic"
1141   [(parallel [(set (pc)
1142                (if_then_else
1143                 (leu (match_operand:SI 0 "s_register_operand" "r")
1144                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
1145                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1146                                  (label_ref:SI (match_operand 2 "" ""))))
1147                 (label_ref:SI (match_operand 3 "" ""))))
1148               (clobber (reg:CC CC_REGNUM))
1149               (clobber (match_scratch:SI 4 "=&r"))
1150               (clobber (match_scratch:SI 5 "=r"))
1151               (use (label_ref:SI (match_dup 2)))])]
1152   "TARGET_THUMB2 && flag_pic"
1153   "* return thumb2_output_casesi(operands);"
1154   [(set_attr "conds" "clob")
1155    (set_attr "length" "20")
1156    (set_attr "type" "multiple")]
1159 (define_insn "*thumb2_return"
1160   [(simple_return)]
1161   "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1162   "* return output_return_instruction (const_true_rtx, true, false, true);"
1163   [(set_attr "type" "branch")
1164    (set_attr "length" "4")]
1167 (define_insn "*thumb2_cmse_entry_return"
1168   [(simple_return)]
1169   "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1170   "* return output_return_instruction (const_true_rtx, true, false, true);"
1171   [(set_attr "type" "branch")
1172    ; This is a return from a cmse_nonsecure_entry function so code will be
1173    ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1174    ; we adapt the length accordingly.
1175    (set (attr "length")
1176      (if_then_else (match_test "TARGET_HARD_FLOAT")
1177       (const_int 34)
1178       (const_int 8)))
1179    ; We do not support predicate execution of returns from cmse_nonsecure_entry
1180    ; functions because we need to clear the APSR.  Since predicable has to be
1181    ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1182    ; functions.
1183    (set_attr "predicable" "no")]
1186 (define_insn_and_split "thumb2_eh_return"
1187   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1188                     VUNSPEC_EH_RETURN)
1189    (clobber (match_scratch:SI 1 "=&r"))]
1190   "TARGET_THUMB2"
1191   "#"
1192   "&& reload_completed"
1193   [(const_int 0)]
1194   "
1195   {
1196     thumb_set_return_address (operands[0], operands[1]);
1197     DONE;
1198   }"
1201 (define_insn "*thumb2_alusi3_short"
1202   [(set (match_operand:SI          0 "s_register_operand" "=l")
1203         (match_operator:SI 3 "thumb_16bit_operator"
1204          [(match_operand:SI 1 "s_register_operand" "0")
1205           (match_operand:SI 2 "s_register_operand" "l")]))
1206    (clobber (reg:CC CC_REGNUM))]
1207   "TARGET_THUMB2 && reload_completed
1208    && GET_CODE(operands[3]) != PLUS
1209    && GET_CODE(operands[3]) != MINUS"
1210   "%I3%!\\t%0, %1, %2"
1211   [(set_attr "predicable" "yes")
1212    (set_attr "length" "2")
1213    (set_attr "type" "alu_sreg")]
1216 (define_insn "*thumb2_shiftsi3_short"
1217   [(set (match_operand:SI   0 "low_register_operand" "=l,l")
1218         (match_operator:SI  3 "shift_operator"
1219          [(match_operand:SI 1 "low_register_operand"  "0,l")
1220           (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1221    (clobber (reg:CC CC_REGNUM))]
1222   "TARGET_THUMB2 && reload_completed
1223    && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1224        || REG_P (operands[2]))"
1225   "* return arm_output_shift(operands, 2);"
1226   [(set_attr "predicable" "yes")
1227    (set_attr "shift" "1")
1228    (set_attr "length" "2")
1229    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1230                       (const_string "alu_shift_imm")
1231                       (const_string "alu_shift_reg")))]
1234 (define_insn "*thumb2_mov<mode>_shortim"
1235   [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1236         (match_operand:QHSI 1 "const_int_operand" "I"))
1237    (clobber (reg:CC CC_REGNUM))]
1238   "TARGET_THUMB2 && reload_completed"
1239   "mov%!\t%0, %1"
1240   [(set_attr "predicable" "yes")
1241    (set_attr "length" "2")
1242    (set_attr "type" "mov_imm")]
1245 (define_insn "*thumb2_addsi_short"
1246   [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1247         (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1248                  (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1249    (clobber (reg:CC CC_REGNUM))]
1250   "TARGET_THUMB2 && reload_completed"
1251   "*
1252     HOST_WIDE_INT val;
1254     if (CONST_INT_P (operands[2]))
1255       val = INTVAL(operands[2]);
1256     else
1257       val = 0;
1259     /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff.  */
1260     if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1261       return \"sub%!\\t%0, %1, #%n2\";
1262     else
1263       return \"add%!\\t%0, %1, %2\";
1264   "
1265   [(set_attr "predicable" "yes")
1266    (set_attr "length" "2")
1267    (set_attr_alternative "type"
1268                          [(if_then_else (match_operand 2 "const_int_operand" "")
1269                                         (const_string "alu_imm")
1270                                         (const_string "alu_sreg"))
1271                           (const_string "alu_imm")])]
1274 (define_insn "*thumb2_subsi_short"
1275   [(set (match_operand:SI 0 "low_register_operand" "=l")
1276         (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1277                   (match_operand:SI 2 "low_register_operand" "l")))
1278    (clobber (reg:CC CC_REGNUM))]
1279   "TARGET_THUMB2 && reload_completed"
1280   "sub%!\\t%0, %1, %2"
1281   [(set_attr "predicable" "yes")
1282    (set_attr "length" "2")
1283    (set_attr "type" "alu_sreg")]
1286 (define_peephole2
1287   [(set (match_operand:CC 0 "cc_register" "")
1288         (compare:CC (match_operand:SI 1 "low_register_operand" "")
1289                     (match_operand:SI 2 "const_int_operand" "")))]
1290   "TARGET_THUMB2
1291    && peep2_reg_dead_p (1, operands[1])
1292    && satisfies_constraint_Pw (operands[2])"
1293   [(parallel
1294     [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1295      (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1296   "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1299 (define_peephole2
1300   [(match_scratch:SI 3 "l")
1301    (set (match_operand:CC 0 "cc_register" "")
1302         (compare:CC (match_operand:SI 1 "low_register_operand" "")
1303                     (match_operand:SI 2 "const_int_operand" "")))]
1304   "TARGET_THUMB2
1305    && satisfies_constraint_Px (operands[2])"
1306   [(parallel
1307     [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1308      (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1309   "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1312 (define_insn "thumb2_addsi3_compare0"
1313   [(set (reg:CC_NOOV CC_REGNUM)
1314         (compare:CC_NOOV
1315           (plus:SI (match_operand:SI 1 "s_register_operand" "l,  0, r")
1316                    (match_operand:SI 2 "arm_add_operand"    "lPt,Ps,rIL"))
1317           (const_int 0)))
1318    (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1319         (plus:SI (match_dup 1) (match_dup 2)))]
1320   "TARGET_THUMB2"
1321   "*
1322     HOST_WIDE_INT val;
1324     if (CONST_INT_P (operands[2]))
1325       val = INTVAL (operands[2]);
1326     else
1327       val = 0;
1329     if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1330       return \"subs\\t%0, %1, #%n2\";
1331     else
1332       return \"adds\\t%0, %1, %2\";
1333   "
1334   [(set_attr "conds" "set")
1335    (set_attr "length" "2,2,4")
1336    (set_attr_alternative "type"
1337                          [(if_then_else (match_operand 2 "const_int_operand" "")
1338                                         (const_string "alus_imm")
1339                                         (const_string "alus_sreg"))
1340                           (const_string "alus_imm")
1341                           (if_then_else (match_operand 2 "const_int_operand" "")
1342                                         (const_string "alus_imm")
1343                                         (const_string "alus_sreg"))])]
1346 (define_insn "*thumb2_addsi3_compare0_scratch"
1347   [(set (reg:CC_NOOV CC_REGNUM)
1348         (compare:CC_NOOV
1349           (plus:SI (match_operand:SI 0 "s_register_operand" "l,  r")
1350                    (match_operand:SI 1 "arm_add_operand"    "lPv,rIL"))
1351           (const_int 0)))]
1352   "TARGET_THUMB2"
1353   "*
1354     HOST_WIDE_INT val;
1356     if (CONST_INT_P (operands[1]))
1357       val = INTVAL (operands[1]);
1358     else
1359       val = 0;
1361     if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1362       return \"cmp\\t%0, #%n1\";
1363     else
1364       return \"cmn\\t%0, %1\";
1365   "
1366   [(set_attr "conds" "set")
1367    (set_attr "length" "2,4")
1368    (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1369                                     (const_string "alus_imm")
1370                                     (const_string "alus_sreg")))]
1373 (define_insn "*thumb2_mulsi_short"
1374   [(set (match_operand:SI 0 "low_register_operand" "=l")
1375         (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1376                  (match_operand:SI 2 "low_register_operand" "l")))
1377    (clobber (reg:CC CC_REGNUM))]
1378   "TARGET_THUMB2 && optimize_size && reload_completed"
1379   "mul%!\\t%0, %2, %0"
1380   [(set_attr "predicable" "yes")
1381    (set_attr "length" "2")
1382    (set_attr "type" "muls")])
1384 (define_insn "*thumb2_mulsi_short_compare0"
1385   [(set (reg:CC_NOOV CC_REGNUM)
1386         (compare:CC_NOOV
1387          (mult:SI (match_operand:SI 1 "register_operand" "%0")
1388                   (match_operand:SI 2 "register_operand" "l"))
1389          (const_int 0)))
1390    (set (match_operand:SI 0 "register_operand" "=l")
1391         (mult:SI (match_dup 1) (match_dup 2)))]
1392   "TARGET_THUMB2 && optimize_size"
1393   "muls\\t%0, %2, %0"
1394   [(set_attr "length" "2")
1395    (set_attr "type" "muls")])
1397 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1398   [(set (reg:CC_NOOV CC_REGNUM)
1399         (compare:CC_NOOV
1400          (mult:SI (match_operand:SI 1 "register_operand" "%0")
1401                   (match_operand:SI 2 "register_operand" "l"))
1402          (const_int 0)))
1403    (clobber (match_scratch:SI 0 "=l"))]
1404   "TARGET_THUMB2 && optimize_size"
1405   "muls\\t%0, %2, %0"
1406   [(set_attr "length" "2")
1407    (set_attr "type" "muls")])
1409 (define_insn "*thumb2_cbz"
1410   [(set (pc) (if_then_else
1411               (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1412                   (const_int 0))
1413               (label_ref (match_operand 1 "" ""))
1414               (pc)))
1415    (clobber (reg:CC CC_REGNUM))]
1416   "TARGET_THUMB2"
1417   "*
1418   if (get_attr_length (insn) == 2)
1419     return \"cbz\\t%0, %l1\";
1420   else
1421     return \"cmp\\t%0, #0\;beq\\t%l1\";
1422   "
1423   [(set (attr "length")
1424         (if_then_else
1425             (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1426                  (le (minus (match_dup 1) (pc)) (const_int 128))
1427                  (not (match_test "which_alternative")))
1428             (const_int 2)
1429             (const_int 8)))
1430    (set_attr "type" "branch,multiple")]
1433 (define_insn "*thumb2_cbnz"
1434   [(set (pc) (if_then_else
1435               (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1436                   (const_int 0))
1437               (label_ref (match_operand 1 "" ""))
1438               (pc)))
1439    (clobber (reg:CC CC_REGNUM))]
1440   "TARGET_THUMB2"
1441   "*
1442   if (get_attr_length (insn) == 2)
1443     return \"cbnz\\t%0, %l1\";
1444   else
1445     return \"cmp\\t%0, #0\;bne\\t%l1\";
1446   "
1447   [(set (attr "length")
1448         (if_then_else
1449             (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1450                  (le (minus (match_dup 1) (pc)) (const_int 128))
1451                  (not (match_test "which_alternative")))
1452             (const_int 2)
1453             (const_int 8)))
1454    (set_attr "type" "branch,multiple")]
1457 (define_insn "*thumb2_one_cmplsi2_short"
1458   [(set (match_operand:SI 0 "low_register_operand" "=l")
1459         (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1460    (clobber (reg:CC CC_REGNUM))]
1461   "TARGET_THUMB2 && reload_completed"
1462   "mvn%!\t%0, %1"
1463   [(set_attr "predicable" "yes")
1464    (set_attr "length" "2")
1465    (set_attr "type" "mvn_reg")]
1468 (define_insn "*thumb2_negsi2_short"
1469   [(set (match_operand:SI 0 "low_register_operand" "=l")
1470         (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1471    (clobber (reg:CC CC_REGNUM))]
1472   "TARGET_THUMB2 && reload_completed"
1473   "rsb%!\t%0, %1, #0"
1474   [(set_attr "predicable" "yes")
1475    (set_attr "length" "2")
1476    (set_attr "type" "alu_sreg")]
1479 ; Constants for op 2 will never be given to these patterns.
1480 (define_insn_and_split "*iordi_notdi_di"
1481   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1482         (ior:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
1483                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1484   "TARGET_THUMB2"
1485   "#"
1486   "TARGET_THUMB2 && reload_completed"
1487   [(set (match_dup 0) (ior:SI (not:SI (match_dup 1)) (match_dup 2)))
1488    (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
1489   "
1490   {
1491     operands[3] = gen_highpart (SImode, operands[0]);
1492     operands[0] = gen_lowpart (SImode, operands[0]);
1493     operands[4] = gen_highpart (SImode, operands[1]);
1494     operands[1] = gen_lowpart (SImode, operands[1]);
1495     operands[5] = gen_highpart (SImode, operands[2]);
1496     operands[2] = gen_lowpart (SImode, operands[2]);
1497   }"
1498   [(set_attr "length" "8")
1499    (set_attr "predicable" "yes")
1500    (set_attr "predicable_short_it" "no")
1501    (set_attr "type" "multiple")]
1504 (define_insn_and_split "*iordi_notzesidi_di"
1505   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1506         (ior:DI (not:DI (zero_extend:DI
1507                          (match_operand:SI 2 "s_register_operand" "r,r")))
1508                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1509   "TARGET_THUMB2"
1510   "#"
1511   ; (not (zero_extend...)) means operand0 will always be 0xffffffff
1512   "TARGET_THUMB2 && reload_completed"
1513   [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1514    (set (match_dup 3) (const_int -1))]
1515   "
1516   {
1517     operands[3] = gen_highpart (SImode, operands[0]);
1518     operands[0] = gen_lowpart (SImode, operands[0]);
1519     operands[1] = gen_lowpart (SImode, operands[1]);
1520   }"
1521   [(set_attr "length" "4,8")
1522    (set_attr "predicable" "yes")
1523    (set_attr "predicable_short_it" "no")
1524    (set_attr "type" "multiple")]
1527 (define_insn_and_split "*iordi_notdi_zesidi"
1528   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1529         (ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "0,?r"))
1530                 (zero_extend:DI
1531                  (match_operand:SI 1 "s_register_operand" "r,r"))))]
1532   "TARGET_THUMB2"
1533   "#"
1534   "TARGET_THUMB2 && reload_completed"
1535   [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1536    (set (match_dup 3) (not:SI (match_dup 4)))]
1537   "
1538   {
1539     operands[3] = gen_highpart (SImode, operands[0]);
1540     operands[0] = gen_lowpart (SImode, operands[0]);
1541     operands[1] = gen_lowpart (SImode, operands[1]);
1542     operands[4] = gen_highpart (SImode, operands[2]);
1543     operands[2] = gen_lowpart (SImode, operands[2]);
1544   }"
1545   [(set_attr "length" "8")
1546    (set_attr "predicable" "yes")
1547    (set_attr "predicable_short_it" "no")
1548    (set_attr "type" "multiple")]
1551 (define_insn_and_split "*iordi_notsesidi_di"
1552   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1553         (ior:DI (not:DI (sign_extend:DI
1554                          (match_operand:SI 2 "s_register_operand" "r,r")))
1555                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1556   "TARGET_THUMB2"
1557   "#"
1558   "TARGET_THUMB2 && reload_completed"
1559   [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1560    (set (match_dup 3) (ior:SI (not:SI
1561                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1562                                (match_dup 4)))]
1563   "
1564   {
1565     operands[3] = gen_highpart (SImode, operands[0]);
1566     operands[0] = gen_lowpart (SImode, operands[0]);
1567     operands[4] = gen_highpart (SImode, operands[1]);
1568     operands[1] = gen_lowpart (SImode, operands[1]);
1569   }"
1570   [(set_attr "length" "8")
1571    (set_attr "predicable" "yes")
1572    (set_attr "predicable_short_it" "no")
1573    (set_attr "type" "multiple")]
1576 (define_insn "*orsi_notsi_si"
1577   [(set (match_operand:SI 0 "s_register_operand" "=r")
1578         (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1579                 (match_operand:SI 1 "s_register_operand" "r")))]
1580   "TARGET_THUMB2"
1581   "orn%?\\t%0, %1, %2"
1582   [(set_attr "predicable" "yes")
1583    (set_attr "type" "logic_reg")]
1586 (define_insn "*orsi_not_shiftsi_si"
1587   [(set (match_operand:SI 0 "s_register_operand" "=r")
1588         (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1589                          [(match_operand:SI 2 "s_register_operand" "r")
1590                           (match_operand:SI 3 "const_int_operand" "M")]))
1591                 (match_operand:SI 1 "s_register_operand" "r")))]
1592   "TARGET_THUMB2"
1593   "orn%?\\t%0, %1, %2%S4"
1594   [(set_attr "predicable" "yes")
1595    (set_attr "shift" "2")
1596    (set_attr "type" "alu_shift_imm")]
1599 (define_peephole2
1600   [(set (match_operand:CC_NOOV 0 "cc_register" "")
1601         (compare:CC_NOOV (zero_extract:SI
1602                           (match_operand:SI 1 "low_register_operand" "")
1603                           (const_int 1)
1604                           (match_operand:SI 2 "const_int_operand" ""))
1605                          (const_int 0)))
1606    (match_scratch:SI 3 "l")
1607    (set (pc)
1608         (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1609                        [(match_dup 0) (const_int 0)])
1610                       (match_operand 5 "" "")
1611                       (match_operand 6 "" "")))]
1612   "TARGET_THUMB2
1613    && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1614    && peep2_reg_dead_p (2, operands[0])"
1615   [(parallel [(set (match_dup 0)
1616                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1617                                     (const_int 0)))
1618               (clobber (match_dup 3))])
1619    (set (pc)
1620         (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1621                       (match_dup 5) (match_dup 6)))]
1622   "
1623   operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1624   operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1625                                 VOIDmode, operands[0], const0_rtx);
1626   ")
1628 (define_peephole2
1629   [(set (match_operand:CC_NOOV 0 "cc_register" "")
1630         (compare:CC_NOOV (zero_extract:SI
1631                           (match_operand:SI 1 "low_register_operand" "")
1632                           (match_operand:SI 2 "const_int_operand" "")
1633                           (const_int 0))
1634                          (const_int 0)))
1635    (match_scratch:SI 3 "l")
1636    (set (pc)
1637         (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1638                        [(match_dup 0) (const_int 0)])
1639                       (match_operand 5 "" "")
1640                       (match_operand 6 "" "")))]
1641   "TARGET_THUMB2
1642    && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1643    && peep2_reg_dead_p (2, operands[0])"
1644   [(parallel [(set (match_dup 0)
1645                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1646                                     (const_int 0)))
1647               (clobber (match_dup 3))])
1648    (set (pc)
1649         (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1650                       (match_dup 5) (match_dup 6)))]
1651   "
1652   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1653   ")
1655 ;; Define the subtract-one-and-jump insns so loop.c
1656 ;; knows what to generate.
1657 (define_expand "doloop_end"
1658   [(use (match_operand 0 "" ""))      ; loop pseudo
1659    (use (match_operand 1 "" ""))]     ; label
1660   "TARGET_32BIT"
1661   "
1663    /* Currently SMS relies on the do-loop pattern to recognize loops
1664       where (1) the control part consists of all insns defining and/or
1665       using a certain 'count' register and (2) the loop count can be
1666       adjusted by modifying this register prior to the loop.
1667       ??? The possible introduction of a new block to initialize the
1668       new IV can potentially affect branch optimizations.  */
1669    if (optimize > 0 && flag_modulo_sched)
1670    {
1671      rtx s0;
1672      rtx bcomp;
1673      rtx loc_ref;
1674      rtx cc_reg;
1675      rtx insn;
1676      rtx cmp;
1678      if (GET_MODE (operands[0]) != SImode)
1679        FAIL;
1681      s0 = operands [0];
1682      if (TARGET_THUMB2)
1683        insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1684      else
1685        insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1687      cmp = XVECEXP (PATTERN (insn), 0, 0);
1688      cc_reg = SET_DEST (cmp);
1689      bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1690      loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1691      emit_jump_insn (gen_rtx_SET (pc_rtx,
1692                                   gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1693                                                         loc_ref, pc_rtx)));
1694      DONE;
1695    }else
1696       FAIL;
1697  }")