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