xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/arm/thumb2.md (revision d11b170b9000ada93db553723522a63d5deac310)
1;; ARM Thumb-2 Machine Description
2;; Copyright (C) 2007, 2008 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(define_insn "*thumb2_incscc"
28  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
29        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
30                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
31                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
32  "TARGET_THUMB2"
33  "@
34  it\\t%d2\;add%d2\\t%0, %1, #1
35  ite\\t%D2\;mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
36  [(set_attr "conds" "use")
37   (set_attr "length" "6,10")]
38)
39
40(define_insn "*thumb2_decscc"
41  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
42        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
43		  (match_operator:SI 2 "arm_comparison_operator"
44                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
45  "TARGET_THUMB2"
46  "@
47   it\\t%d2\;sub%d2\\t%0, %1, #1
48   ite\\t%D2\;mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
49  [(set_attr "conds" "use")
50   (set_attr "length" "6,10")]
51)
52
53;; Thumb-2 only allows shift by constant on data processing instructions
54(define_insn "*thumb_andsi_not_shiftsi_si"
55  [(set (match_operand:SI 0 "s_register_operand" "=r")
56	(and:SI (not:SI (match_operator:SI 4 "shift_operator"
57			 [(match_operand:SI 2 "s_register_operand" "r")
58			  (match_operand:SI 3 "const_int_operand" "M")]))
59		(match_operand:SI 1 "s_register_operand" "r")))]
60  "TARGET_THUMB2"
61  "bic%?\\t%0, %1, %2%S4"
62  [(set_attr "predicable" "yes")
63   (set_attr "shift" "2")
64   (set_attr "type" "alu_shift")]
65)
66
67(define_insn "*thumb2_smaxsi3"
68  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
69	(smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
70		 (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
71   (clobber (reg:CC CC_REGNUM))]
72  "TARGET_THUMB2"
73  "@
74   cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
75   cmp\\t%1, %2\;it\\tge\;movge\\t%0, %1
76   cmp\\t%1, %2\;ite\\tge\;movge\\t%0, %1\;movlt\\t%0, %2"
77  [(set_attr "conds" "clob")
78   (set_attr "length" "10,10,14")]
79)
80
81(define_insn "*thumb2_sminsi3"
82  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
83	(smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
84		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
85   (clobber (reg:CC CC_REGNUM))]
86  "TARGET_THUMB2"
87  "@
88   cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
89   cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %1
90   cmp\\t%1, %2\;ite\\tlt\;movlt\\t%0, %1\;movge\\t%0, %2"
91  [(set_attr "conds" "clob")
92   (set_attr "length" "10,10,14")]
93)
94
95(define_insn "*thumb32_umaxsi3"
96  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
97	(umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
98		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
99   (clobber (reg:CC CC_REGNUM))]
100  "TARGET_THUMB2"
101  "@
102   cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
103   cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %1
104   cmp\\t%1, %2\;ite\\tcs\;movcs\\t%0, %1\;movcc\\t%0, %2"
105  [(set_attr "conds" "clob")
106   (set_attr "length" "10,10,14")]
107)
108
109(define_insn "*thumb2_uminsi3"
110  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
111	(umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
112		 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
113   (clobber (reg:CC CC_REGNUM))]
114  "TARGET_THUMB2"
115  "@
116   cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
117   cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %1
118   cmp\\t%1, %2\;ite\\tcc\;movcc\\t%0, %1\;movcs\\t%0, %2"
119  [(set_attr "conds" "clob")
120   (set_attr "length" "10,10,14")]
121)
122
123(define_insn "*thumb2_notsi_shiftsi"
124  [(set (match_operand:SI 0 "s_register_operand" "=r")
125	(not:SI (match_operator:SI 3 "shift_operator"
126		 [(match_operand:SI 1 "s_register_operand" "r")
127		  (match_operand:SI 2 "const_int_operand"  "M")])))]
128  "TARGET_THUMB2"
129  "mvn%?\\t%0, %1%S3"
130  [(set_attr "predicable" "yes")
131   (set_attr "shift" "1")
132   (set_attr "type" "alu_shift")]
133)
134
135(define_insn "*thumb2_notsi_shiftsi_compare0"
136  [(set (reg:CC_NOOV CC_REGNUM)
137	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
138			  [(match_operand:SI 1 "s_register_operand" "r")
139			   (match_operand:SI 2 "const_int_operand"  "M")]))
140			 (const_int 0)))
141   (set (match_operand:SI 0 "s_register_operand" "=r")
142	(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
143  "TARGET_THUMB2"
144  "mvn%.\\t%0, %1%S3"
145  [(set_attr "conds" "set")
146   (set_attr "shift" "1")
147   (set_attr "type" "alu_shift")]
148)
149
150(define_insn "*thumb2_not_shiftsi_compare0_scratch"
151  [(set (reg:CC_NOOV CC_REGNUM)
152	(compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
153			  [(match_operand:SI 1 "s_register_operand" "r")
154			   (match_operand:SI 2 "const_int_operand"  "M")]))
155			 (const_int 0)))
156   (clobber (match_scratch:SI 0 "=r"))]
157  "TARGET_THUMB2"
158  "mvn%.\\t%0, %1%S3"
159  [(set_attr "conds" "set")
160   (set_attr "shift" "1")
161   (set_attr "type" "alu_shift")]
162)
163
164;; Thumb-2 does not have rsc, so use a clever trick with shifter operands.
165(define_insn "*thumb2_negdi2"
166  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
167	(neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
168   (clobber (reg:CC CC_REGNUM))]
169  "TARGET_THUMB2"
170  "negs\\t%Q0, %Q1\;sbc\\t%R0, %R1, %R1, lsl #1"
171  [(set_attr "conds" "clob")
172   (set_attr "length" "8")]
173)
174
175(define_insn "*thumb2_abssi2"
176  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
177	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
178   (clobber (reg:CC CC_REGNUM))]
179  "TARGET_THUMB2"
180  "@
181   cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
182   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
183  [(set_attr "conds" "clob,*")
184   (set_attr "shift" "1")
185   ;; predicable can't be set based on the variant, so left as no
186   (set_attr "length" "10,8")]
187)
188
189(define_insn "*thumb2_neg_abssi2"
190  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
191	(neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
192   (clobber (reg:CC CC_REGNUM))]
193  "TARGET_THUMB2"
194  "@
195   cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
196   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
197  [(set_attr "conds" "clob,*")
198   (set_attr "shift" "1")
199   ;; predicable can't be set based on the variant, so left as no
200   (set_attr "length" "10,8")]
201)
202
203(define_insn "*thumb2_movdi"
204  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
205	(match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
206  "TARGET_THUMB2
207  && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
208  && !TARGET_IWMMXT"
209  "*
210  switch (which_alternative)
211    {
212    case 0:
213    case 1:
214    case 2:
215      return \"#\";
216    default:
217      return output_move_double (operands);
218    }
219  "
220  [(set_attr "length" "8,12,16,8,8")
221   (set_attr "type" "*,*,*,load2,store2")
222   (set_attr "pool_range" "*,*,*,4096,*")
223   (set_attr "neg_pool_range" "*,*,*,0,*")]
224)
225
226(define_insn "*thumb2_movsi_insn"
227  [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
228	(match_operand:SI 1 "general_operand"	   "rk ,I,K,j,mi,rk"))]
229  "TARGET_THUMB2 && ! TARGET_IWMMXT
230   && !(TARGET_HARD_FLOAT && TARGET_VFP)
231   && (   register_operand (operands[0], SImode)
232       || register_operand (operands[1], SImode))"
233  "@
234   mov%?\\t%0, %1
235   mov%?\\t%0, %1
236   mvn%?\\t%0, #%B1
237   movw%?\\t%0, %1
238   ldr%?\\t%0, %1
239   str%?\\t%1, %0"
240  [(set_attr "type" "*,*,*,*,load1,store1")
241   (set_attr "predicable" "yes")
242   (set_attr "pool_range" "*,*,*,*,4096,*")
243   (set_attr "neg_pool_range" "*,*,*,*,0,*")]
244)
245
246(define_insn "tls_load_dot_plus_four"
247  [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
248	(mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
249			    (const_int 4)
250			    (match_operand 3 "" "")]
251			   UNSPEC_PIC_BASE)))
252   (clobber (match_scratch:SI 1 "=X,l,X,r"))]
253  "TARGET_THUMB2"
254  "*
255  (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
256			     INTVAL (operands[3]));
257  return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
258  "
259  [(set_attr "length" "4,4,6,6")]
260)
261
262;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
263;; of the messiness associated with the ARM patterns.
264(define_insn "*thumb2_movhi_insn"
265  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
266	(match_operand:HI 1 "general_operand"      "rI,n,r,m"))]
267  "TARGET_THUMB2"
268  "@
269   mov%?\\t%0, %1\\t%@ movhi
270   movw%?\\t%0, %L1\\t%@ movhi
271   str%(h%)\\t%1, %0\\t%@ movhi
272   ldr%(h%)\\t%0, %1\\t%@ movhi"
273  [(set_attr "type" "*,*,store1,load1")
274   (set_attr "predicable" "yes")
275   (set_attr "pool_range" "*,*,*,4096")
276   (set_attr "neg_pool_range" "*,*,*,250")]
277)
278
279(define_insn "*thumb2_movsf_soft_insn"
280  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
281	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
282  "TARGET_THUMB2
283   && TARGET_SOFT_FLOAT
284   && (GET_CODE (operands[0]) != MEM
285       || register_operand (operands[1], SFmode))"
286  "@
287   mov%?\\t%0, %1
288   ldr%?\\t%0, %1\\t%@ float
289   str%?\\t%1, %0\\t%@ float"
290  [(set_attr "predicable" "yes")
291   (set_attr "type" "*,load1,store1")
292   (set_attr "pool_range" "*,4096,*")
293   (set_attr "neg_pool_range" "*,0,*")]
294)
295
296(define_insn "*thumb2_movdf_soft_insn"
297  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
298	(match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
299  "TARGET_THUMB2 && TARGET_SOFT_FLOAT
300   && (   register_operand (operands[0], DFmode)
301       || register_operand (operands[1], DFmode))"
302  "*
303  switch (which_alternative)
304    {
305    case 0:
306    case 1:
307    case 2:
308      return \"#\";
309    default:
310      return output_move_double (operands);
311    }
312  "
313  [(set_attr "length" "8,12,16,8,8")
314   (set_attr "type" "*,*,*,load2,store2")
315   (set_attr "pool_range" "1020")
316   (set_attr "neg_pool_range" "0")]
317)
318
319(define_insn "*thumb2_cmpsi_shiftsi"
320  [(set (reg:CC CC_REGNUM)
321	(compare:CC (match_operand:SI   0 "s_register_operand" "r")
322		    (match_operator:SI  3 "shift_operator"
323		     [(match_operand:SI 1 "s_register_operand" "r")
324		      (match_operand:SI 2 "const_int_operand"  "M")])))]
325  "TARGET_THUMB2"
326  "cmp%?\\t%0, %1%S3"
327  [(set_attr "conds" "set")
328   (set_attr "shift" "1")
329   (set_attr "type" "alu_shift")]
330)
331
332(define_insn "*thumb2_cmpsi_shiftsi_swp"
333  [(set (reg:CC_SWP CC_REGNUM)
334	(compare:CC_SWP (match_operator:SI 3 "shift_operator"
335			 [(match_operand:SI 1 "s_register_operand" "r")
336			  (match_operand:SI 2 "const_int_operand" "M")])
337			(match_operand:SI 0 "s_register_operand" "r")))]
338  "TARGET_THUMB2"
339  "cmp%?\\t%0, %1%S3"
340  [(set_attr "conds" "set")
341   (set_attr "shift" "1")
342   (set_attr "type" "alu_shift")]
343)
344
345(define_insn "*thumb2_cmpsi_neg_shiftsi"
346  [(set (reg:CC CC_REGNUM)
347	(compare:CC (match_operand:SI 0 "s_register_operand" "r")
348		    (neg:SI (match_operator:SI 3 "shift_operator"
349			     [(match_operand:SI 1 "s_register_operand" "r")
350			      (match_operand:SI 2 "const_int_operand" "M")]))))]
351  "TARGET_THUMB2"
352  "cmn%?\\t%0, %1%S3"
353  [(set_attr "conds" "set")
354   (set_attr "shift" "1")
355   (set_attr "type" "alu_shift")]
356)
357
358(define_insn "*thumb2_mov_scc"
359  [(set (match_operand:SI 0 "s_register_operand" "=r")
360	(match_operator:SI 1 "arm_comparison_operator"
361	 [(match_operand 2 "cc_register" "") (const_int 0)]))]
362  "TARGET_THUMB2"
363  "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
364  [(set_attr "conds" "use")
365   (set_attr "length" "10")]
366)
367
368(define_insn "*thumb2_mov_negscc"
369  [(set (match_operand:SI 0 "s_register_operand" "=r")
370	(neg:SI (match_operator:SI 1 "arm_comparison_operator"
371		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
372  "TARGET_THUMB2"
373  "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
374  [(set_attr "conds" "use")
375   (set_attr "length" "10")]
376)
377
378(define_insn "*thumb2_mov_notscc"
379  [(set (match_operand:SI 0 "s_register_operand" "=r")
380	(not:SI (match_operator:SI 1 "arm_comparison_operator"
381		 [(match_operand 2 "cc_register" "") (const_int 0)])))]
382  "TARGET_THUMB2"
383  "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
384  [(set_attr "conds" "use")
385   (set_attr "length" "10")]
386)
387
388(define_insn "*thumb2_movsicc_insn"
389  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
390	(if_then_else:SI
391	 (match_operator 3 "arm_comparison_operator"
392	  [(match_operand 4 "cc_register" "") (const_int 0)])
393	 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
394	 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
395  "TARGET_THUMB2"
396  "@
397   it\\t%D3\;mov%D3\\t%0, %2
398   it\\t%D3\;mvn%D3\\t%0, #%B2
399   it\\t%d3\;mov%d3\\t%0, %1
400   it\\t%d3\;mvn%d3\\t%0, #%B1
401   ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
402   ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
403   ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
404   ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
405  [(set_attr "length" "6,6,6,6,10,10,10,10")
406   (set_attr "conds" "use")]
407)
408
409(define_insn "*thumb2_movsfcc_soft_insn"
410  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
411	(if_then_else:SF (match_operator 3 "arm_comparison_operator"
412			  [(match_operand 4 "cc_register" "") (const_int 0)])
413			 (match_operand:SF 1 "s_register_operand" "0,r")
414			 (match_operand:SF 2 "s_register_operand" "r,0")))]
415  "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
416  "@
417   it\\t%D3\;mov%D3\\t%0, %2
418   it\\t%d3\;mov%d3\\t%0, %1"
419  [(set_attr "length" "6,6")
420   (set_attr "conds" "use")]
421)
422
423(define_insn "*call_reg_thumb2"
424  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
425         (match_operand 1 "" ""))
426   (use (match_operand 2 "" ""))
427   (clobber (reg:SI LR_REGNUM))]
428  "TARGET_THUMB2"
429  "blx%?\\t%0"
430  [(set_attr "type" "call")]
431)
432
433(define_insn "*call_value_reg_thumb2"
434  [(set (match_operand 0 "" "")
435	(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
436	      (match_operand 2 "" "")))
437   (use (match_operand 3 "" ""))
438   (clobber (reg:SI LR_REGNUM))]
439  "TARGET_THUMB2"
440  "blx\\t%1"
441  [(set_attr "type" "call")]
442)
443
444(define_insn "*thumb2_indirect_jump"
445  [(set (pc)
446	(match_operand:SI 0 "register_operand" "l*r"))]
447  "TARGET_THUMB2"
448  "bx\\t%0"
449  [(set_attr "conds" "clob")]
450)
451;; Don't define thumb2_load_indirect_jump because we can't guarantee label
452;; addresses will have the thumb bit set correctly.
453
454
455;; Patterns to allow combination of arithmetic, cond code and shifts
456
457(define_insn "*thumb2_arith_shiftsi"
458  [(set (match_operand:SI 0 "s_register_operand" "=r")
459        (match_operator:SI 1 "shiftable_operator"
460          [(match_operator:SI 3 "shift_operator"
461             [(match_operand:SI 4 "s_register_operand" "r")
462              (match_operand:SI 5 "const_int_operand" "M")])
463           (match_operand:SI 2 "s_register_operand" "r")]))]
464  "TARGET_THUMB2"
465  "%i1%?\\t%0, %2, %4%S3"
466  [(set_attr "predicable" "yes")
467   (set_attr "shift" "4")
468   (set_attr "type" "alu_shift")]
469)
470
471;; ??? What does this splitter do?  Copied from the ARM version
472(define_split
473  [(set (match_operand:SI 0 "s_register_operand" "")
474	(match_operator:SI 1 "shiftable_operator"
475	 [(match_operator:SI 2 "shiftable_operator"
476	   [(match_operator:SI 3 "shift_operator"
477	     [(match_operand:SI 4 "s_register_operand" "")
478	      (match_operand:SI 5 "const_int_operand" "")])
479	    (match_operand:SI 6 "s_register_operand" "")])
480	  (match_operand:SI 7 "arm_rhs_operand" "")]))
481   (clobber (match_operand:SI 8 "s_register_operand" ""))]
482  "TARGET_32BIT"
483  [(set (match_dup 8)
484	(match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
485			 (match_dup 6)]))
486   (set (match_dup 0)
487	(match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
488  "")
489
490(define_insn "*thumb2_arith_shiftsi_compare0"
491  [(set (reg:CC_NOOV CC_REGNUM)
492        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
493		          [(match_operator:SI 3 "shift_operator"
494		            [(match_operand:SI 4 "s_register_operand" "r")
495		             (match_operand:SI 5 "const_int_operand" "M")])
496		           (match_operand:SI 2 "s_register_operand" "r")])
497			 (const_int 0)))
498   (set (match_operand:SI 0 "s_register_operand" "=r")
499	(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
500			 (match_dup 2)]))]
501  "TARGET_32BIT"
502  "%i1%.\\t%0, %2, %4%S3"
503  [(set_attr "conds" "set")
504   (set_attr "shift" "4")
505   (set_attr "type" "alu_shift")]
506)
507
508(define_insn "*thumb2_arith_shiftsi_compare0_scratch"
509  [(set (reg:CC_NOOV CC_REGNUM)
510        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
511		          [(match_operator:SI 3 "shift_operator"
512		            [(match_operand:SI 4 "s_register_operand" "r")
513		             (match_operand:SI 5 "const_int_operand" "M")])
514		           (match_operand:SI 2 "s_register_operand" "r")])
515			 (const_int 0)))
516   (clobber (match_scratch:SI 0 "=r"))]
517  "TARGET_THUMB2"
518  "%i1%.\\t%0, %2, %4%S3"
519  [(set_attr "conds" "set")
520   (set_attr "shift" "4")
521   (set_attr "type" "alu_shift")]
522)
523
524(define_insn "*thumb2_sub_shiftsi"
525  [(set (match_operand:SI 0 "s_register_operand" "=r")
526	(minus:SI (match_operand:SI 1 "s_register_operand" "r")
527		  (match_operator:SI 2 "shift_operator"
528		   [(match_operand:SI 3 "s_register_operand" "r")
529		    (match_operand:SI 4 "const_int_operand" "M")])))]
530  "TARGET_THUMB2"
531  "sub%?\\t%0, %1, %3%S2"
532  [(set_attr "predicable" "yes")
533   (set_attr "shift" "3")
534   (set_attr "type" "alu_shift")]
535)
536
537(define_insn "*thumb2_sub_shiftsi_compare0"
538  [(set (reg:CC_NOOV CC_REGNUM)
539	(compare:CC_NOOV
540	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
541		   (match_operator:SI 2 "shift_operator"
542		    [(match_operand:SI 3 "s_register_operand" "r")
543		     (match_operand:SI 4 "const_int_operand" "M")]))
544	 (const_int 0)))
545   (set (match_operand:SI 0 "s_register_operand" "=r")
546	(minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
547						 (match_dup 4)])))]
548  "TARGET_THUMB2"
549  "sub%.\\t%0, %1, %3%S2"
550  [(set_attr "conds" "set")
551   (set_attr "shift" "3")
552   (set_attr "type" "alu_shift")]
553)
554
555(define_insn "*thumb2_sub_shiftsi_compare0_scratch"
556  [(set (reg:CC_NOOV CC_REGNUM)
557	(compare:CC_NOOV
558	 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
559		   (match_operator:SI 2 "shift_operator"
560		    [(match_operand:SI 3 "s_register_operand" "r")
561		     (match_operand:SI 4 "const_int_operand" "M")]))
562	 (const_int 0)))
563   (clobber (match_scratch:SI 0 "=r"))]
564  "TARGET_THUMB2"
565  "sub%.\\t%0, %1, %3%S2"
566  [(set_attr "conds" "set")
567   (set_attr "shift" "3")
568   (set_attr "type" "alu_shift")]
569)
570
571(define_insn "*thumb2_and_scc"
572  [(set (match_operand:SI 0 "s_register_operand" "=r")
573	(and:SI (match_operator:SI 1 "arm_comparison_operator"
574		 [(match_operand 3 "cc_register" "") (const_int 0)])
575		(match_operand:SI 2 "s_register_operand" "r")))]
576  "TARGET_THUMB2"
577  "ite\\t%D1\;mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
578  [(set_attr "conds" "use")
579   (set_attr "length" "10")]
580)
581
582(define_insn "*thumb2_ior_scc"
583  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
584	(ior:SI (match_operator:SI 2 "arm_comparison_operator"
585		 [(match_operand 3 "cc_register" "") (const_int 0)])
586		(match_operand:SI 1 "s_register_operand" "0,?r")))]
587  "TARGET_THUMB2"
588  "@
589   it\\t%d2\;orr%d2\\t%0, %1, #1
590   ite\\t%D2\;mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
591  [(set_attr "conds" "use")
592   (set_attr "length" "6,10")]
593)
594
595(define_insn "*thumb2_compare_scc"
596  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
597	(match_operator:SI 1 "arm_comparison_operator"
598	 [(match_operand:SI 2 "s_register_operand" "r,r")
599	  (match_operand:SI 3 "arm_add_operand" "rI,L")]))
600   (clobber (reg:CC CC_REGNUM))]
601  "TARGET_THUMB2"
602  "*
603    if (operands[3] == const0_rtx)
604      {
605	if (GET_CODE (operands[1]) == LT)
606	  return \"lsr\\t%0, %2, #31\";
607
608	if (GET_CODE (operands[1]) == GE)
609	  return \"mvn\\t%0, %2\;lsr\\t%0, %0, #31\";
610
611	if (GET_CODE (operands[1]) == EQ)
612	  return \"rsbs\\t%0, %2, #1\;it\\tcc\;movcc\\t%0, #0\";
613      }
614
615    if (GET_CODE (operands[1]) == NE)
616      {
617        if (which_alternative == 1)
618	  return \"adds\\t%0, %2, #%n3\;it\\tne\;movne\\t%0, #1\";
619        return \"subs\\t%0, %2, %3\;it\\tne\;movne\\t%0, #1\";
620      }
621    if (which_alternative == 1)
622      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
623    else
624      output_asm_insn (\"cmp\\t%2, %3\", operands);
625    return \"ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
626  "
627  [(set_attr "conds" "clob")
628   (set_attr "length" "14")]
629)
630
631(define_insn "*thumb2_cond_move"
632  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
633	(if_then_else:SI (match_operator 3 "equality_operator"
634			  [(match_operator 4 "arm_comparison_operator"
635			    [(match_operand 5 "cc_register" "") (const_int 0)])
636			   (const_int 0)])
637			 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
638			 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
639  "TARGET_THUMB2"
640  "*
641    if (GET_CODE (operands[3]) == NE)
642      {
643        if (which_alternative != 1)
644	  output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
645        if (which_alternative != 0)
646	  output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
647        return \"\";
648      }
649    switch (which_alternative)
650      {
651      case 0:
652	output_asm_insn (\"it\\t%d4\", operands);
653	break;
654      case 1:
655	output_asm_insn (\"it\\t%D4\", operands);
656	break;
657      case 2:
658	output_asm_insn (\"ite\\t%D4\", operands);
659	break;
660      default:
661	abort();
662      }
663    if (which_alternative != 0)
664      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
665    if (which_alternative != 1)
666      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
667    return \"\";
668  "
669  [(set_attr "conds" "use")
670   (set_attr "length" "6,6,10")]
671)
672
673(define_insn "*thumb2_cond_arith"
674  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
675        (match_operator:SI 5 "shiftable_operator"
676	 [(match_operator:SI 4 "arm_comparison_operator"
677           [(match_operand:SI 2 "s_register_operand" "r,r")
678	    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
679          (match_operand:SI 1 "s_register_operand" "0,?r")]))
680   (clobber (reg:CC CC_REGNUM))]
681  "TARGET_THUMB2"
682  "*
683    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
684      return \"%i5\\t%0, %1, %2, lsr #31\";
685
686    output_asm_insn (\"cmp\\t%2, %3\", operands);
687    if (GET_CODE (operands[5]) == AND)
688      {
689	output_asm_insn (\"ite\\t%D4\", operands);
690	output_asm_insn (\"mov%D4\\t%0, #0\", operands);
691      }
692    else if (GET_CODE (operands[5]) == MINUS)
693      {
694	output_asm_insn (\"ite\\t%D4\", operands);
695	output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
696      }
697    else if (which_alternative != 0)
698      {
699	output_asm_insn (\"ite\\t%D4\", operands);
700	output_asm_insn (\"mov%D4\\t%0, %1\", operands);
701      }
702    else
703      output_asm_insn (\"it\\t%d4\", operands);
704    return \"%i5%d4\\t%0, %1, #1\";
705  "
706  [(set_attr "conds" "clob")
707   (set_attr "length" "14")]
708)
709
710(define_insn "*thumb2_cond_sub"
711  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
712        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
713		  (match_operator:SI 4 "arm_comparison_operator"
714                   [(match_operand:SI 2 "s_register_operand" "r,r")
715		    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
716   (clobber (reg:CC CC_REGNUM))]
717  "TARGET_THUMB2"
718  "*
719    output_asm_insn (\"cmp\\t%2, %3\", operands);
720    if (which_alternative != 0)
721      {
722	output_asm_insn (\"ite\\t%D4\", operands);
723	output_asm_insn (\"mov%D4\\t%0, %1\", operands);
724      }
725    else
726      output_asm_insn (\"it\\t%d4\", operands);
727    return \"sub%d4\\t%0, %1, #1\";
728  "
729  [(set_attr "conds" "clob")
730   (set_attr "length" "10,14")]
731)
732
733(define_insn "*thumb2_negscc"
734  [(set (match_operand:SI 0 "s_register_operand" "=r")
735	(neg:SI (match_operator 3 "arm_comparison_operator"
736		 [(match_operand:SI 1 "s_register_operand" "r")
737		  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
738   (clobber (reg:CC CC_REGNUM))]
739  "TARGET_THUMB2"
740  "*
741  if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
742    return \"asr\\t%0, %1, #31\";
743
744  if (GET_CODE (operands[3]) == NE)
745    return \"subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0\";
746
747  output_asm_insn (\"cmp\\t%1, %2\", operands);
748  output_asm_insn (\"ite\\t%D3\", operands);
749  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
750  return \"mvn%d3\\t%0, #0\";
751  "
752  [(set_attr "conds" "clob")
753   (set_attr "length" "14")]
754)
755
756(define_insn "*thumb2_movcond"
757  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
758	(if_then_else:SI
759	 (match_operator 5 "arm_comparison_operator"
760	  [(match_operand:SI 3 "s_register_operand" "r,r,r")
761	   (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
762	 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
763	 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
764   (clobber (reg:CC CC_REGNUM))]
765  "TARGET_THUMB2"
766  "*
767  if (GET_CODE (operands[5]) == LT
768      && (operands[4] == const0_rtx))
769    {
770      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
771	{
772	  if (operands[2] == const0_rtx)
773	    return \"and\\t%0, %1, %3, asr #31\";
774	  return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
775	}
776      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
777	{
778	  if (operands[1] == const0_rtx)
779	    return \"bic\\t%0, %2, %3, asr #31\";
780	  return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
781	}
782      /* The only case that falls through to here is when both ops 1 & 2
783	 are constants.  */
784    }
785
786  if (GET_CODE (operands[5]) == GE
787      && (operands[4] == const0_rtx))
788    {
789      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
790	{
791	  if (operands[2] == const0_rtx)
792	    return \"bic\\t%0, %1, %3, asr #31\";
793	  return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
794	}
795      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
796	{
797	  if (operands[1] == const0_rtx)
798	    return \"and\\t%0, %2, %3, asr #31\";
799	  return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
800	}
801      /* The only case that falls through to here is when both ops 1 & 2
802	 are constants.  */
803    }
804  if (GET_CODE (operands[4]) == CONST_INT
805      && !const_ok_for_arm (INTVAL (operands[4])))
806    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
807  else
808    output_asm_insn (\"cmp\\t%3, %4\", operands);
809  switch (which_alternative)
810    {
811    case 0:
812      output_asm_insn (\"it\\t%D5\", operands);
813      break;
814    case 1:
815      output_asm_insn (\"it\\t%d5\", operands);
816      break;
817    case 2:
818      output_asm_insn (\"ite\\t%d5\", operands);
819      break;
820    default:
821      abort();
822    }
823  if (which_alternative != 0)
824    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
825  if (which_alternative != 1)
826    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
827  return \"\";
828  "
829  [(set_attr "conds" "clob")
830   (set_attr "length" "10,10,14")]
831)
832
833;; Zero and sign extension instructions.
834
835(define_insn_and_split "*thumb2_zero_extendsidi2"
836  [(set (match_operand:DI 0 "s_register_operand" "=r")
837        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
838  "TARGET_THUMB2"
839  "mov%?\\t%Q0, %1\;mov%?\\t%R0, #0"
840  "&& reload_completed"
841  [(set (match_dup 0) (match_dup 1))]
842  "
843  {
844    rtx lo_part = gen_lowpart (SImode, operands[0]);
845    if (!REG_P (lo_part) || REGNO (lo_part) != REGNO (operands[1]))
846      emit_move_insn (lo_part, operands[1]);
847    operands[0] = gen_highpart (SImode, operands[0]);
848    operands[1] = const0_rtx;
849  }
850  "
851  [(set_attr "length" "8")
852   (set_attr "ce_count" "2")
853   (set_attr "predicable" "yes")]
854)
855
856(define_insn_and_split "*thumb2_zero_extendhidi2"
857  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
858	(zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
859  "TARGET_THUMB2"
860  "@
861   uxth%?\\t%Q0, %1\;mov%?\\t%R0, #0
862   ldr%(h%)\\t%Q0, %1\;mov%?\\t%R0, #0"
863  "&& reload_completed"
864  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
865   (set (match_dup 2) (match_dup 3))]
866  "
867  {
868    operands[2] = gen_highpart (SImode, operands[0]);
869    operands[0] = gen_lowpart (SImode, operands[0]);
870    operands[3] = const0_rtx;
871  }
872  "
873  [(set_attr "length" "8")
874   (set_attr "ce_count" "2")
875   (set_attr "predicable" "yes")
876   (set_attr "type" "*,load_byte")
877   (set_attr "pool_range" "*,4092")
878   (set_attr "neg_pool_range" "*,250")]
879)
880
881(define_insn_and_split "*thumb2_zero_extendqidi2"
882  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
883	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
884  "TARGET_THUMB2"
885  "@
886   uxtb%?\\t%Q0, %1\;mov%?\\t%R0, #0
887   ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
888  "&& reload_completed"
889  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
890   (set (match_dup 2) (match_dup 3))]
891  "
892  {
893    operands[2] = gen_highpart (SImode, operands[0]);
894    operands[0] = gen_lowpart (SImode, operands[0]);
895    operands[3] = const0_rtx;
896  }
897  "
898  [(set_attr "length" "8")
899   (set_attr "ce_count" "2")
900   (set_attr "predicable" "yes")
901   (set_attr "type" "*,load_byte")
902   (set_attr "pool_range" "*,4092")
903   (set_attr "neg_pool_range" "*,250")]
904)
905
906(define_insn_and_split "*thumb2_extendsidi2"
907  [(set (match_operand:DI 0 "s_register_operand" "=r")
908        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
909  "TARGET_THUMB2"
910  "mov%?\\t%Q0, %1\;asr?\\t%R0, %1, #31"
911  "&& reload_completed"
912  [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
913  {
914    rtx lo_part = gen_lowpart (SImode, operands[0]);
915
916    if (!REG_P (lo_part) || REGNO (lo_part) != REGNO (operands[1]))
917      emit_move_insn (lo_part, operands[1]);
918    operands[0] = gen_highpart (SImode, operands[0]);
919  }
920  [(set_attr "length" "8")
921   (set_attr "ce_count" "2")
922   (set_attr "shift" "1")
923   (set_attr "predicable" "yes")]
924)
925
926(define_insn_and_split "*thumb2_extendhidi2"
927  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
928	(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
929  "TARGET_THUMB2"
930  "@
931   sxth%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31
932   ldrsh%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31"
933  "&& reload_completed"
934  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
935   (set (match_dup 2) (ashiftrt:SI (match_dup 0) (const_int 31)))]
936  "
937  {
938    operands[2] = gen_highpart (SImode, operands[0]);
939    operands[0] = gen_lowpart (SImode, operands[0]);
940  }
941  "
942  [(set_attr "length" "8")
943   (set_attr "ce_count" "2")
944   (set_attr "predicable" "yes")
945   (set_attr "type" "*,load_byte")
946   (set_attr "pool_range" "*,4092")
947   (set_attr "neg_pool_range" "*,250")]
948)
949
950(define_insn_and_split "*thumb2_extendqidi2"
951  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
952	(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
953  "TARGET_THUMB2"
954  "@
955   sxtb%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31
956   ldrsb%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31"
957  "&& reload_completed"
958  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
959   (set (match_dup 2) (ashiftrt:SI (match_dup 0) (const_int 31)))]
960  "
961  {
962    operands[2] = gen_highpart (SImode, operands[0]);
963    operands[0] = gen_lowpart (SImode, operands[0]);
964  }
965  "
966  [(set_attr "length" "8")
967   (set_attr "ce_count" "2")
968   (set_attr "predicable" "yes")
969   (set_attr "type" "*,load_byte")
970   (set_attr "pool_range" "*,4092")
971   (set_attr "neg_pool_range" "*,250")]
972)
973
974;; All supported Thumb2 implementations are armv6, so only that case is
975;; provided.
976(define_insn "*thumb2_extendqisi_v6"
977  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
978	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
979  "TARGET_THUMB2 && arm_arch6"
980  "@
981   sxtb%?\\t%0, %1
982   ldr%(sb%)\\t%0, %1"
983  [(set_attr "type" "alu_shift,load_byte")
984   (set_attr "predicable" "yes")
985   (set_attr "pool_range" "*,4096")
986   (set_attr "neg_pool_range" "*,250")]
987)
988
989(define_insn "*thumb2_zero_extendhisi2_v6"
990  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
991	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
992  "TARGET_THUMB2 && arm_arch6"
993  "@
994   uxth%?\\t%0, %1
995   ldr%(h%)\\t%0, %1"
996  [(set_attr "type" "alu_shift,load_byte")
997   (set_attr "predicable" "yes")
998   (set_attr "pool_range" "*,4096")
999   (set_attr "neg_pool_range" "*,250")]
1000)
1001
1002(define_insn "*thumb2_zero_extendqisi2_v6"
1003  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1004	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1005  "TARGET_THUMB2 && arm_arch6"
1006  "@
1007   uxtb%(%)\\t%0, %1
1008   ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
1009  [(set_attr "type" "alu_shift,load_byte")
1010   (set_attr "predicable" "yes")
1011   (set_attr "pool_range" "*,4096")
1012   (set_attr "neg_pool_range" "*,250")]
1013)
1014
1015(define_insn "thumb2_casesi_internal"
1016  [(parallel [(set (pc)
1017	       (if_then_else
1018		(leu (match_operand:SI 0 "s_register_operand" "r")
1019		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
1020		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1021				 (label_ref (match_operand 2 "" ""))))
1022		(label_ref (match_operand 3 "" ""))))
1023	      (clobber (reg:CC CC_REGNUM))
1024	      (clobber (match_scratch:SI 4 "=&r"))
1025	      (use (label_ref (match_dup 2)))])]
1026  "TARGET_THUMB2 && !flag_pic"
1027  "* return thumb2_output_casesi(operands);"
1028  [(set_attr "conds" "clob")
1029   (set_attr "length" "16")]
1030)
1031
1032(define_insn "thumb2_casesi_internal_pic"
1033  [(parallel [(set (pc)
1034	       (if_then_else
1035		(leu (match_operand:SI 0 "s_register_operand" "r")
1036		     (match_operand:SI 1 "arm_rhs_operand" "rI"))
1037		(mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1038				 (label_ref (match_operand 2 "" ""))))
1039		(label_ref (match_operand 3 "" ""))))
1040	      (clobber (reg:CC CC_REGNUM))
1041	      (clobber (match_scratch:SI 4 "=&r"))
1042	      (clobber (match_scratch:SI 5 "=r"))
1043	      (use (label_ref (match_dup 2)))])]
1044  "TARGET_THUMB2 && flag_pic"
1045  "* return thumb2_output_casesi(operands);"
1046  [(set_attr "conds" "clob")
1047   (set_attr "length" "20")]
1048)
1049
1050(define_insn_and_split "thumb2_eh_return"
1051  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1052		    VUNSPEC_EH_RETURN)
1053   (clobber (match_scratch:SI 1 "=&r"))]
1054  "TARGET_THUMB2"
1055  "#"
1056  "&& reload_completed"
1057  [(const_int 0)]
1058  "
1059  {
1060    thumb_set_return_address (operands[0], operands[1]);
1061    DONE;
1062  }"
1063)
1064
1065;; Peepholes and insns for 16-bit flag clobbering instructions.
1066;; The conditional forms of these instructions do not clobber CC.
1067;; However by the time peepholes are run it is probably too late to do
1068;; anything useful with this information.
1069(define_peephole2
1070  [(set (match_operand:SI          0 "low_register_operand" "")
1071        (match_operator:SI 3 "thumb_16bit_operator"
1072	 [(match_operand:SI 1  "low_register_operand" "")
1073	  (match_operand:SI 2 "low_register_operand" "")]))]
1074  "TARGET_THUMB2
1075   && (rtx_equal_p(operands[0], operands[1])
1076       || GET_CODE(operands[3]) == PLUS
1077       || GET_CODE(operands[3]) == MINUS)
1078   && peep2_regno_dead_p(0, CC_REGNUM)"
1079  [(parallel
1080    [(set (match_dup 0)
1081	  (match_op_dup 3
1082	   [(match_dup 1)
1083	    (match_dup 2)]))
1084     (clobber (reg:CC CC_REGNUM))])]
1085  ""
1086)
1087
1088(define_insn "*thumb2_alusi3_short"
1089  [(set (match_operand:SI          0 "s_register_operand" "=l")
1090        (match_operator:SI 3 "thumb_16bit_operator"
1091	 [(match_operand:SI 1 "s_register_operand" "0")
1092	  (match_operand:SI 2 "s_register_operand" "l")]))
1093   (clobber (reg:CC CC_REGNUM))]
1094  "TARGET_THUMB2 && reload_completed
1095   && GET_CODE(operands[3]) != PLUS
1096   && GET_CODE(operands[3]) != MINUS"
1097  "%I3%!\\t%0, %1, %2"
1098  [(set_attr "predicable" "yes")
1099   (set_attr "length" "2")]
1100)
1101
1102;; Similarly for 16-bit shift instructions
1103;; There is no 16-bit rotate by immediate instruction.
1104(define_peephole2
1105  [(set (match_operand:SI   0 "low_register_operand" "")
1106	(match_operator:SI  3 "shift_operator"
1107	 [(match_operand:SI 1 "low_register_operand" "")
1108	  (match_operand:SI 2 "low_reg_or_int_operand" "")]))]
1109  "TARGET_THUMB2
1110   && peep2_regno_dead_p(0, CC_REGNUM)
1111   && (CONST_INT_P (operands[2]) || operands[1] == operands[0])
1112   && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1113       || REG_P(operands[2]))"
1114  [(parallel
1115    [(set (match_dup 0)
1116	  (match_op_dup 3
1117	   [(match_dup 1)
1118	    (match_dup 2)]))
1119     (clobber (reg:CC CC_REGNUM))])]
1120  ""
1121)
1122
1123(define_insn "*thumb2_shiftsi3_short"
1124  [(set (match_operand:SI   0 "low_register_operand" "=l,l")
1125	(match_operator:SI  3 "shift_operator"
1126	 [(match_operand:SI 1 "low_register_operand"  "0,l")
1127	  (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1128   (clobber (reg:CC CC_REGNUM))]
1129  "TARGET_THUMB2 && reload_completed
1130   && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1131       || REG_P(operands[2]))"
1132  "* return arm_output_shift(operands, 2);"
1133  [(set_attr "predicable" "yes")
1134   (set_attr "shift" "1")
1135   (set_attr "length" "2")
1136   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1137		      (const_string "alu_shift")
1138		      (const_string "alu_shift_reg")))]
1139)
1140
1141;; 16-bit load immediate
1142(define_peephole2
1143  [(set (match_operand:QHSI 0 "low_register_operand" "")
1144	(match_operand:QHSI 1 "const_int_operand" ""))]
1145  "TARGET_THUMB2
1146   && peep2_regno_dead_p(0, CC_REGNUM)
1147   && (unsigned HOST_WIDE_INT) INTVAL(operands[1]) < 256"
1148  [(parallel
1149    [(set (match_dup 0)
1150	  (match_dup 1))
1151     (clobber (reg:CC CC_REGNUM))])]
1152  ""
1153)
1154
1155(define_insn "*thumb2_mov<mode>_shortim"
1156  [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1157	(match_operand:QHSI 1 "const_int_operand" "I"))
1158   (clobber (reg:CC CC_REGNUM))]
1159  "TARGET_THUMB2 && reload_completed"
1160  "mov%!\t%0, %1"
1161  [(set_attr "predicable" "yes")
1162   (set_attr "length" "2")]
1163)
1164
1165;; 16-bit add/sub immediate
1166(define_peephole2
1167  [(set (match_operand:SI 0 "low_register_operand" "")
1168	(plus:SI (match_operand:SI 1 "low_register_operand" "")
1169		 (match_operand:SI 2 "const_int_operand" "")))]
1170  "TARGET_THUMB2
1171   && peep2_regno_dead_p(0, CC_REGNUM)
1172   && ((rtx_equal_p(operands[0], operands[1])
1173	&& INTVAL(operands[2]) > -256 && INTVAL(operands[2]) < 256)
1174       || (INTVAL(operands[2]) > -8 && INTVAL(operands[2]) < 8))"
1175  [(parallel
1176    [(set (match_dup 0)
1177	  (plus:SI (match_dup 1)
1178		   (match_dup 2)))
1179     (clobber (reg:CC CC_REGNUM))])]
1180  ""
1181)
1182
1183(define_insn "*thumb2_addsi_short"
1184  [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1185	(plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1186		 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1187   (clobber (reg:CC CC_REGNUM))]
1188  "TARGET_THUMB2 && reload_completed"
1189  "*
1190    HOST_WIDE_INT val;
1191
1192    if (GET_CODE (operands[2]) == CONST_INT)
1193      val = INTVAL(operands[2]);
1194    else
1195      val = 0;
1196
1197    /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff.  */
1198    if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1199      return \"sub%!\\t%0, %1, #%n2\";
1200    else
1201      return \"add%!\\t%0, %1, %2\";
1202  "
1203  [(set_attr "predicable" "yes")
1204   (set_attr "length" "2")]
1205)
1206
1207(define_insn "divsi3"
1208  [(set (match_operand:SI	  0 "s_register_operand" "=r")
1209	(div:SI (match_operand:SI 1 "s_register_operand"  "r")
1210		(match_operand:SI 2 "s_register_operand"  "r")))]
1211  "(TARGET_THUMB2 || TARGET_ARM) && arm_arch_hwdiv"
1212  "sdiv%?\t%0, %1, %2"
1213  [(set_attr "predicable" "yes")
1214   (set_attr "insn" "sdiv")]
1215)
1216
1217(define_insn "udivsi3"
1218  [(set (match_operand:SI	   0 "s_register_operand" "=r")
1219	(udiv:SI (match_operand:SI 1 "s_register_operand"  "r")
1220		 (match_operand:SI 2 "s_register_operand"  "r")))]
1221  "(TARGET_THUMB2 || TARGET_ARM) && arm_arch_hwdiv"
1222  "udiv%?\t%0, %1, %2"
1223  [(set_attr "predicable" "yes")
1224   (set_attr "insn" "udiv")]
1225)
1226
1227(define_insn "*thumb2_subsi_short"
1228  [(set (match_operand:SI 0 "low_register_operand" "=l")
1229	(minus:SI (match_operand:SI 1 "low_register_operand" "l")
1230		  (match_operand:SI 2 "low_register_operand" "l")))
1231   (clobber (reg:CC CC_REGNUM))]
1232  "TARGET_THUMB2 && reload_completed"
1233  "sub%!\\t%0, %1, %2"
1234  [(set_attr "predicable" "yes")
1235   (set_attr "length" "2")]
1236)
1237
1238;; 16-bit encodings of "muls" and "mul<c>".  We only use these when
1239;; optimizing for size since "muls" is slow on all known
1240;; implementations and since "mul<c>" will be generated by
1241;; "*arm_mulsi3_v6" anyhow.  The assembler will use a 16-bit encoding
1242;; for "mul<c>" whenever possible anyhow.
1243(define_peephole2
1244  [(set (match_operand:SI 0 "low_register_operand" "")
1245        (mult:SI (match_operand:SI 1 "low_register_operand" "")
1246                 (match_dup 0)))]
1247  "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)"
1248  [(parallel
1249    [(set (match_dup 0)
1250           (mult:SI (match_dup 0) (match_dup 1)))
1251     (clobber (reg:CC CC_REGNUM))])]
1252  ""
1253)
1254
1255(define_peephole2
1256  [(set (match_operand:SI 0 "low_register_operand" "")
1257        (mult:SI (match_dup 0)
1258	         (match_operand:SI 1 "low_register_operand" "")))]
1259  "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)"
1260  [(parallel
1261    [(set (match_dup 0)
1262           (mult:SI (match_dup 0) (match_dup 1)))
1263     (clobber (reg:CC CC_REGNUM))])]
1264  ""
1265)
1266
1267(define_insn "*thumb2_mulsi_short"
1268  [(set (match_operand:SI 0 "low_register_operand" "=l")
1269        (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1270                 (match_operand:SI 2 "low_register_operand" "l")))
1271   (clobber (reg:CC CC_REGNUM))]
1272  "TARGET_THUMB2 && optimize_size && reload_completed"
1273  "mul%!\\t%0, %2, %0"
1274  [(set_attr "predicable" "yes")
1275   (set_attr "length" "2")
1276   (set_attr "insn" "muls")])
1277
1278(define_insn "*thumb2_mulsi_short_compare0"
1279  [(set (reg:CC_NOOV CC_REGNUM)
1280        (compare:CC_NOOV
1281         (mult:SI (match_operand:SI 1 "register_operand" "%0")
1282	          (match_operand:SI 2 "register_operand" "l"))
1283         (const_int 0)))
1284   (set (match_operand:SI 0 "register_operand" "=l")
1285	(mult:SI (match_dup 1) (match_dup 2)))]
1286  "TARGET_THUMB2 && optimize_size"
1287  "muls\\t%0, %2, %0"
1288  [(set_attr "length" "2")
1289   (set_attr "insn" "muls")])
1290
1291(define_insn "*thumb2_mulsi_short_compare0_scratch"
1292  [(set (reg:CC_NOOV CC_REGNUM)
1293        (compare:CC_NOOV
1294         (mult:SI (match_operand:SI 1 "register_operand" "%0")
1295	          (match_operand:SI 2 "register_operand" "l"))
1296         (const_int 0)))
1297   (clobber (match_scratch:SI 0 "=l"))]
1298  "TARGET_THUMB2 && optimize_size"
1299  "muls\\t%0, %2, %0"
1300  [(set_attr "length" "2")
1301   (set_attr "insn" "muls")])
1302
1303(define_insn "*thumb2_cbz"
1304  [(set (pc) (if_then_else
1305	      (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1306		  (const_int 0))
1307	      (label_ref (match_operand 1 "" ""))
1308	      (pc)))
1309   (clobber (reg:CC CC_REGNUM))]
1310  "TARGET_THUMB2"
1311  "*
1312  if (get_attr_length (insn) == 2)
1313    return \"cbz\\t%0, %l1\";
1314  else
1315    return \"cmp\\t%0, #0\;beq\\t%l1\";
1316  "
1317  [(set (attr "length")
1318        (if_then_else
1319	    (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1320	         (le (minus (match_dup 1) (pc)) (const_int 128))
1321	         (eq (symbol_ref ("which_alternative")) (const_int 0)))
1322	    (const_int 2)
1323	    (const_int 8)))]
1324)
1325
1326(define_insn "*thumb2_cbnz"
1327  [(set (pc) (if_then_else
1328	      (ne (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 \"cbnz\\t%0, %l1\";
1337  else
1338    return \"cmp\\t%0, #0\;bne\\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	         (eq (symbol_ref ("which_alternative")) (const_int 0)))
1345	    (const_int 2)
1346	    (const_int 8)))]
1347)
1348
1349;; 16-bit complement
1350(define_peephole2
1351  [(set (match_operand:SI 0 "low_register_operand" "")
1352	(not:SI (match_operand:SI 1 "low_register_operand" "")))]
1353  "TARGET_THUMB2
1354   && peep2_regno_dead_p(0, CC_REGNUM)"
1355  [(parallel
1356    [(set (match_dup 0)
1357	  (not:SI (match_dup 1)))
1358     (clobber (reg:CC CC_REGNUM))])]
1359  ""
1360)
1361
1362(define_insn "*thumb2_one_cmplsi2_short"
1363  [(set (match_operand:SI 0 "low_register_operand" "=l")
1364	(not:SI (match_operand:SI 1 "low_register_operand" "l")))
1365   (clobber (reg:CC CC_REGNUM))]
1366  "TARGET_THUMB2 && reload_completed"
1367  "mvn%!\t%0, %1"
1368  [(set_attr "predicable" "yes")
1369   (set_attr "length" "2")]
1370)
1371
1372;; 16-bit negate
1373(define_peephole2
1374  [(set (match_operand:SI 0 "low_register_operand" "")
1375	(neg:SI (match_operand:SI 1 "low_register_operand" "")))]
1376  "TARGET_THUMB2
1377   && peep2_regno_dead_p(0, CC_REGNUM)"
1378  [(parallel
1379    [(set (match_dup 0)
1380	  (neg:SI (match_dup 1)))
1381     (clobber (reg:CC CC_REGNUM))])]
1382  ""
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)
1394
1395(define_insn "orsi_notsi_si"
1396  [(set (match_operand:SI 0 "s_register_operand" "=r")
1397	(ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1398		(match_operand:SI 1 "s_register_operand" "r")))]
1399  "TARGET_THUMB2"
1400  "orn%?\\t%0, %1, %2"
1401  [(set_attr "predicable" "yes")]
1402)
1403
1404(define_insn "*thumb_orsi_not_shiftsi_si"
1405  [(set (match_operand:SI 0 "s_register_operand" "=r")
1406	(ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1407			 [(match_operand:SI 2 "s_register_operand" "r")
1408			  (match_operand:SI 3 "const_int_operand" "M")]))
1409		(match_operand:SI 1 "s_register_operand" "r")))]
1410  "TARGET_THUMB2"
1411  "orn%?\\t%0, %1, %2%S4"
1412  [(set_attr "predicable" "yes")
1413   (set_attr "shift" "2")
1414   (set_attr "type" "alu_shift")]
1415)
1416
1417(define_insn_and_split "*thumb2_iorsi3"
1418  [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1419	(ior:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1420		(match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1421  "TARGET_THUMB2"
1422  "@
1423   orr%?\\t%0, %1, %2
1424   orn%?\\t%0, %1, #%B2
1425   #"
1426  "TARGET_THUMB2
1427   && GET_CODE (operands[2]) == CONST_INT
1428   && !(const_ok_for_arm (INTVAL (operands[2]))
1429	|| const_ok_for_arm (~INTVAL (operands[2])))"
1430  [(clobber (const_int 0))]
1431  "
1432  arm_split_constant  (IOR, SImode, curr_insn,
1433	               INTVAL (operands[2]), operands[0], operands[1], 0);
1434  DONE;
1435  "
1436  [(set_attr "length" "4,4,16")
1437   (set_attr "predicable" "yes")]
1438)
1439