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