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