]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/thumb2.md
thumb2.md (thumb2_smaxsi3,thumb2_sminsi3): Convert define_insn to define_insn_and_split.
[thirdparty/gcc.git] / gcc / config / arm / thumb2.md
1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery, LLC.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>. */
20
21 ;; Note: Thumb-2 is the variant of the Thumb architecture that adds
22 ;; 32-bit encodings of [almost all of] the Arm instruction set.
23 ;; Some old documents refer to the relatively minor interworking
24 ;; changes made in armv5t as "thumb2". These are considered part
25 ;; the 16-bit Thumb-1 instruction set.
26
27 ;; Thumb-2 only allows shift by constant on data processing instructions
28 (define_insn "*thumb_andsi_not_shiftsi_si"
29 [(set (match_operand:SI 0 "s_register_operand" "=r")
30 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
31 [(match_operand:SI 2 "s_register_operand" "r")
32 (match_operand:SI 3 "const_int_operand" "M")]))
33 (match_operand:SI 1 "s_register_operand" "r")))]
34 "TARGET_THUMB2"
35 "bic%?\\t%0, %1, %2%S4"
36 [(set_attr "predicable" "yes")
37 (set_attr "shift" "2")
38 (set_attr "type" "alu_shift")]
39 )
40
41 (define_insn_and_split "*thumb2_smaxsi3"
42 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
43 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
44 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
45 (clobber (reg:CC CC_REGNUM))]
46 "TARGET_THUMB2"
47 "#"
48 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
49 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %1
50 ; cmp\\t%1, %2\;ite\\tge\;movge\\t%0, %1\;movlt\\t%0, %2
51 "TARGET_THUMB2"
52 [(set (reg:CC CC_REGNUM)
53 (compare:CC (match_dup 1) (match_dup 2)))
54 (set (match_dup 0)
55 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
56 (match_dup 1)
57 (match_dup 2)))]
58 ""
59 [(set_attr "conds" "clob")
60 (set_attr "length" "10,10,14")]
61 )
62
63 (define_insn_and_split "*thumb2_sminsi3"
64 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
65 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
66 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
67 (clobber (reg:CC CC_REGNUM))]
68 "TARGET_THUMB2"
69 "#"
70 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
71 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %1
72 ; cmp\\t%1, %2\;ite\\tlt\;movlt\\t%0, %1\;movge\\t%0, %2"
73 "TARGET_THUMB2"
74 [(set (reg:CC CC_REGNUM)
75 (compare:CC (match_dup 1) (match_dup 2)))
76 (set (match_dup 0)
77 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
78 (match_dup 1)
79 (match_dup 2)))]
80 ""
81 [(set_attr "conds" "clob")
82 (set_attr "length" "10,10,14")]
83 )
84
85 (define_insn_and_split "*thumb32_umaxsi3"
86 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
88 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
89 (clobber (reg:CC CC_REGNUM))]
90 "TARGET_THUMB2"
91 "#"
92 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
93 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %1
94 ; cmp\\t%1, %2\;ite\\tcs\;movcs\\t%0, %1\;movcc\\t%0, %2"
95 "TARGET_THUMB2"
96 [(set (reg:CC CC_REGNUM)
97 (compare:CC (match_dup 1) (match_dup 2)))
98 (set (match_dup 0)
99 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
100 (match_dup 1)
101 (match_dup 2)))]
102 ""
103 [(set_attr "conds" "clob")
104 (set_attr "length" "10,10,14")]
105 )
106
107 (define_insn_and_split "*thumb2_uminsi3"
108 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
109 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
110 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
111 (clobber (reg:CC CC_REGNUM))]
112 "TARGET_THUMB2"
113 "#"
114 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
115 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %1
116 ; cmp\\t%1, %2\;ite\\tcc\;movcc\\t%0, %1\;movcs\\t%0, %2"
117 "TARGET_THUMB2"
118 [(set (reg:CC CC_REGNUM)
119 (compare:CC (match_dup 1) (match_dup 2)))
120 (set (match_dup 0)
121 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
122 (match_dup 1)
123 (match_dup 2)))]
124 ""
125 [(set_attr "conds" "clob")
126 (set_attr "length" "10,10,14")]
127 )
128
129 ;; Thumb-2 does not have rsc, so use a clever trick with shifter operands.
130 (define_insn_and_split "*thumb2_negdi2"
131 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
132 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
133 (clobber (reg:CC CC_REGNUM))]
134 "TARGET_THUMB2"
135 "#" ; negs\\t%Q0, %Q1\;sbc\\t%R0, %R1, %R1, lsl #1
136 "&& reload_completed"
137 [(parallel [(set (reg:CC CC_REGNUM)
138 (compare:CC (const_int 0) (match_dup 1)))
139 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
140 (set (match_dup 2) (minus:SI (minus:SI (match_dup 3)
141 (ashift:SI (match_dup 3)
142 (const_int 1)))
143 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
144 {
145 operands[2] = gen_highpart (SImode, operands[0]);
146 operands[0] = gen_lowpart (SImode, operands[0]);
147 operands[3] = gen_highpart (SImode, operands[1]);
148 operands[1] = gen_lowpart (SImode, operands[1]);
149 }
150 [(set_attr "conds" "clob")
151 (set_attr "length" "8")]
152 )
153
154 (define_insn_and_split "*thumb2_abssi2"
155 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
156 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
157 (clobber (reg:CC CC_REGNUM))]
158 "TARGET_THUMB2"
159 "#"
160 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
161 ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
162 "&& reload_completed"
163 [(const_int 0)]
164 {
165 /* if (which_alternative == 0) */
166 if (REGNO(operands[0]) == REGNO(operands[1]))
167 {
168 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
169
170 emit_insn (gen_rtx_SET (VOIDmode,
171 cc_reg,
172 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
173 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
174 (gen_rtx_LT (SImode,
175 cc_reg,
176 const0_rtx)),
177 (gen_rtx_SET (VOIDmode,
178 operands[0],
179 (gen_rtx_MINUS (SImode,
180 const0_rtx,
181 operands[1]))))));
182 }
183 else
184 {
185 emit_insn (gen_rtx_SET (VOIDmode,
186 operands[0],
187 gen_rtx_XOR (SImode,
188 gen_rtx_ASHIFTRT (SImode,
189 operands[1],
190 GEN_INT (31)),
191 operands[1])));
192 emit_insn (gen_rtx_SET (VOIDmode,
193 operands[0],
194 gen_rtx_MINUS (SImode,
195 operands[0],
196 gen_rtx_ASHIFTRT (SImode,
197 operands[1],
198 GEN_INT (31)))));
199 }
200 DONE;
201 }
202 [(set_attr "conds" "clob,*")
203 (set_attr "shift" "1")
204 (set_attr "predicable" "no, yes")
205 (set_attr "ce_count" "2")
206 (set_attr "length" "10,8")]
207 )
208
209 (define_insn_and_split "*thumb2_neg_abssi2"
210 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
211 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
212 (clobber (reg:CC CC_REGNUM))]
213 "TARGET_THUMB2"
214 "#"
215 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
216 ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
217 "&& reload_completed"
218 [(const_int 0)]
219 {
220 /* if (which_alternative == 0) */
221 if (REGNO(operands[0]) == REGNO(operands[1]))
222 {
223 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
224
225 emit_insn (gen_rtx_SET (VOIDmode,
226 cc_reg,
227 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
228 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
229 (gen_rtx_GT (SImode,
230 cc_reg,
231 const0_rtx)),
232 (gen_rtx_SET (VOIDmode,
233 operands[0],
234 (gen_rtx_MINUS (SImode,
235 const0_rtx,
236 operands[1]))))));
237 }
238 else
239 {
240 emit_insn (gen_rtx_SET (VOIDmode,
241 operands[0],
242 gen_rtx_XOR (SImode,
243 gen_rtx_ASHIFTRT (SImode,
244 operands[1],
245 GEN_INT (31)),
246 operands[1])));
247 emit_insn (gen_rtx_SET (VOIDmode,
248 operands[0],
249 gen_rtx_MINUS (SImode,
250 gen_rtx_ASHIFTRT (SImode,
251 operands[1],
252 GEN_INT (31)),
253 operands[0])));
254 }
255 DONE;
256 }
257 [(set_attr "conds" "clob,*")
258 (set_attr "shift" "1")
259 (set_attr "predicable" "no, yes")
260 (set_attr "ce_count" "2")
261 (set_attr "length" "10,8")]
262 )
263
264 ;; We have two alternatives here for memory loads (and similarly for stores)
265 ;; to reflect the fact that the permissible constant pool ranges differ
266 ;; between ldr instructions taking low regs and ldr instructions taking high
267 ;; regs. The high register alternatives are not taken into account when
268 ;; choosing register preferences in order to reflect their expense.
269 (define_insn "*thumb2_movsi_insn"
270 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,l ,*hk,m,*m")
271 (match_operand:SI 1 "general_operand" "rk ,I,K,j,mi,*mi,l,*hk"))]
272 "TARGET_THUMB2 && ! TARGET_IWMMXT
273 && !(TARGET_HARD_FLOAT && TARGET_VFP)
274 && ( register_operand (operands[0], SImode)
275 || register_operand (operands[1], SImode))"
276 "@
277 mov%?\\t%0, %1
278 mov%?\\t%0, %1
279 mvn%?\\t%0, #%B1
280 movw%?\\t%0, %1
281 ldr%?\\t%0, %1
282 ldr%?\\t%0, %1
283 str%?\\t%1, %0
284 str%?\\t%1, %0"
285 [(set_attr "type" "*,*,simple_alu_imm,*,load1,load1,store1,store1")
286 (set_attr "predicable" "yes")
287 (set_attr "pool_range" "*,*,*,*,1018,4094,*,*")
288 (set_attr "neg_pool_range" "*,*,*,*,0,0,*,*")]
289 )
290
291 (define_insn "tls_load_dot_plus_four"
292 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
293 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
294 (const_int 4)
295 (match_operand 3 "" "")]
296 UNSPEC_PIC_BASE)))
297 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
298 "TARGET_THUMB2"
299 "*
300 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
301 INTVAL (operands[3]));
302 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
303 "
304 [(set_attr "length" "4,4,6,6")]
305 )
306
307 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
308 ;; of the messiness associated with the ARM patterns.
309 (define_insn "*thumb2_movhi_insn"
310 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
311 (match_operand:HI 1 "general_operand" "rI,n,r,m"))]
312 "TARGET_THUMB2
313 && (register_operand (operands[0], HImode)
314 || register_operand (operands[1], HImode))"
315 "@
316 mov%?\\t%0, %1\\t%@ movhi
317 movw%?\\t%0, %L1\\t%@ movhi
318 str%(h%)\\t%1, %0\\t%@ movhi
319 ldr%(h%)\\t%0, %1\\t%@ movhi"
320 [(set_attr "type" "*,*,store1,load1")
321 (set_attr "predicable" "yes")
322 (set_attr "pool_range" "*,*,*,4094")
323 (set_attr "neg_pool_range" "*,*,*,250")]
324 )
325
326 (define_insn "*thumb2_cmpsi_neg_shiftsi"
327 [(set (reg:CC CC_REGNUM)
328 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
329 (neg:SI (match_operator:SI 3 "shift_operator"
330 [(match_operand:SI 1 "s_register_operand" "r")
331 (match_operand:SI 2 "const_int_operand" "M")]))))]
332 "TARGET_THUMB2"
333 "cmn%?\\t%0, %1%S3"
334 [(set_attr "conds" "set")
335 (set_attr "shift" "1")
336 (set_attr "type" "alu_shift")]
337 )
338
339 (define_insn_and_split "*thumb2_mov_scc"
340 [(set (match_operand:SI 0 "s_register_operand" "=r")
341 (match_operator:SI 1 "arm_comparison_operator"
342 [(match_operand 2 "cc_register" "") (const_int 0)]))]
343 "TARGET_THUMB2"
344 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
345 "TARGET_THUMB2"
346 [(set (match_dup 0)
347 (if_then_else:SI (match_dup 1)
348 (const_int 1)
349 (const_int 0)))]
350 ""
351 [(set_attr "conds" "use")
352 (set_attr "length" "10")]
353 )
354
355 (define_insn_and_split "*thumb2_mov_negscc"
356 [(set (match_operand:SI 0 "s_register_operand" "=r")
357 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
358 [(match_operand 2 "cc_register" "") (const_int 0)])))]
359 "TARGET_THUMB2"
360 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
361 "TARGET_THUMB2"
362 [(set (match_dup 0)
363 (if_then_else:SI (match_dup 1)
364 (match_dup 3)
365 (const_int 0)))]
366 {
367 operands[3] = GEN_INT (~0);
368 }
369 [(set_attr "conds" "use")
370 (set_attr "length" "10")]
371 )
372
373 (define_insn_and_split "*thumb2_mov_notscc"
374 [(set (match_operand:SI 0 "s_register_operand" "=r")
375 (not:SI (match_operator:SI 1 "arm_comparison_operator"
376 [(match_operand 2 "cc_register" "") (const_int 0)])))]
377 "TARGET_THUMB2"
378 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
379 "TARGET_THUMB2"
380 [(set (match_dup 0)
381 (if_then_else:SI (match_dup 1)
382 (match_dup 3)
383 (match_dup 4)))]
384 {
385 operands[3] = GEN_INT (~1);
386 operands[4] = GEN_INT (~0);
387 }
388 [(set_attr "conds" "use")
389 (set_attr "length" "10")]
390 )
391
392 (define_insn_and_split "*thumb2_movsicc_insn"
393 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
394 (if_then_else:SI
395 (match_operator 3 "arm_comparison_operator"
396 [(match_operand 4 "cc_register" "") (const_int 0)])
397 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
398 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
399 "TARGET_THUMB2"
400 "@
401 it\\t%D3\;mov%D3\\t%0, %2
402 it\\t%D3\;mvn%D3\\t%0, #%B2
403 it\\t%d3\;mov%d3\\t%0, %1
404 it\\t%d3\;mvn%d3\\t%0, #%B1
405 #
406 #
407 #
408 #"
409 ; alt 4: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
410 ; alt 5: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
411 ; alt 6: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
412 ; alt 7: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
413 "&& reload_completed"
414 [(const_int 0)]
415 {
416 enum rtx_code rev_code;
417 enum machine_mode mode;
418 rtx rev_cond;
419
420 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
421 operands[3],
422 gen_rtx_SET (VOIDmode,
423 operands[0],
424 operands[1])));
425 rev_code = GET_CODE (operands[3]);
426 mode = GET_MODE (operands[4]);
427 if (mode == CCFPmode || mode == CCFPEmode)
428 rev_code = reverse_condition_maybe_unordered (rev_code);
429 else
430 rev_code = reverse_condition (rev_code);
431
432 rev_cond = gen_rtx_fmt_ee (rev_code,
433 VOIDmode,
434 gen_rtx_REG (mode, CC_REGNUM),
435 const0_rtx);
436 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
437 rev_cond,
438 gen_rtx_SET (VOIDmode,
439 operands[0],
440 operands[2])));
441 DONE;
442 }
443 [(set_attr "length" "6,6,6,6,10,10,10,10")
444 (set_attr "conds" "use")]
445 )
446
447 (define_insn "*thumb2_movsfcc_soft_insn"
448 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
449 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
450 [(match_operand 4 "cc_register" "") (const_int 0)])
451 (match_operand:SF 1 "s_register_operand" "0,r")
452 (match_operand:SF 2 "s_register_operand" "r,0")))]
453 "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
454 "@
455 it\\t%D3\;mov%D3\\t%0, %2
456 it\\t%d3\;mov%d3\\t%0, %1"
457 [(set_attr "length" "6,6")
458 (set_attr "conds" "use")]
459 )
460
461 (define_insn "*call_reg_thumb2"
462 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
463 (match_operand 1 "" ""))
464 (use (match_operand 2 "" ""))
465 (clobber (reg:SI LR_REGNUM))]
466 "TARGET_THUMB2"
467 "blx%?\\t%0"
468 [(set_attr "type" "call")]
469 )
470
471 (define_insn "*call_value_reg_thumb2"
472 [(set (match_operand 0 "" "")
473 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
474 (match_operand 2 "" "")))
475 (use (match_operand 3 "" ""))
476 (clobber (reg:SI LR_REGNUM))]
477 "TARGET_THUMB2"
478 "blx\\t%1"
479 [(set_attr "type" "call")]
480 )
481
482 (define_insn "*thumb2_indirect_jump"
483 [(set (pc)
484 (match_operand:SI 0 "register_operand" "l*r"))]
485 "TARGET_THUMB2"
486 "bx\\t%0"
487 [(set_attr "conds" "clob")]
488 )
489 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
490 ;; addresses will have the thumb bit set correctly.
491
492
493 (define_insn_and_split "*thumb2_and_scc"
494 [(set (match_operand:SI 0 "s_register_operand" "=r")
495 (and:SI (match_operator:SI 1 "arm_comparison_operator"
496 [(match_operand 2 "cc_register" "") (const_int 0)])
497 (match_operand:SI 3 "s_register_operand" "r")))]
498 "TARGET_THUMB2"
499 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
500 "&& reload_completed"
501 [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
502 (cond_exec (match_dup 4) (set (match_dup 0)
503 (and:SI (match_dup 3) (const_int 1))))]
504 {
505 enum machine_mode mode = GET_MODE (operands[2]);
506 enum rtx_code rc = GET_CODE (operands[1]);
507
508 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
509 if (mode == CCFPmode || mode == CCFPEmode)
510 rc = reverse_condition_maybe_unordered (rc);
511 else
512 rc = reverse_condition (rc);
513 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
514 }
515 [(set_attr "conds" "use")
516 (set_attr "length" "10")]
517 )
518
519 (define_insn_and_split "*thumb2_ior_scc"
520 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
521 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
522 [(match_operand 2 "cc_register" "") (const_int 0)])
523 (match_operand:SI 3 "s_register_operand" "0,?r")))]
524 "TARGET_THUMB2"
525 "@
526 it\\t%d1\;orr%d1\\t%0, %3, #1
527 #"
528 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
529 "&& reload_completed
530 && REGNO (operands [0]) != REGNO (operands[3])"
531 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
532 (cond_exec (match_dup 4) (set (match_dup 0)
533 (ior:SI (match_dup 3) (const_int 1))))]
534 {
535 enum machine_mode mode = GET_MODE (operands[2]);
536 enum rtx_code rc = GET_CODE (operands[1]);
537
538 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
539 if (mode == CCFPmode || mode == CCFPEmode)
540 rc = reverse_condition_maybe_unordered (rc);
541 else
542 rc = reverse_condition (rc);
543 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
544 }
545 [(set_attr "conds" "use")
546 (set_attr "length" "6,10")]
547 )
548
549 (define_insn "*thumb2_cond_move"
550 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
551 (if_then_else:SI (match_operator 3 "equality_operator"
552 [(match_operator 4 "arm_comparison_operator"
553 [(match_operand 5 "cc_register" "") (const_int 0)])
554 (const_int 0)])
555 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
556 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
557 "TARGET_THUMB2"
558 "*
559 if (GET_CODE (operands[3]) == NE)
560 {
561 if (which_alternative != 1)
562 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
563 if (which_alternative != 0)
564 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
565 return \"\";
566 }
567 switch (which_alternative)
568 {
569 case 0:
570 output_asm_insn (\"it\\t%d4\", operands);
571 break;
572 case 1:
573 output_asm_insn (\"it\\t%D4\", operands);
574 break;
575 case 2:
576 output_asm_insn (\"ite\\t%D4\", operands);
577 break;
578 default:
579 abort();
580 }
581 if (which_alternative != 0)
582 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
583 if (which_alternative != 1)
584 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
585 return \"\";
586 "
587 [(set_attr "conds" "use")
588 (set_attr "length" "6,6,10")]
589 )
590
591 (define_insn "*thumb2_cond_arith"
592 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
593 (match_operator:SI 5 "shiftable_operator"
594 [(match_operator:SI 4 "arm_comparison_operator"
595 [(match_operand:SI 2 "s_register_operand" "r,r")
596 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
597 (match_operand:SI 1 "s_register_operand" "0,?r")]))
598 (clobber (reg:CC CC_REGNUM))]
599 "TARGET_THUMB2"
600 "*
601 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
602 return \"%i5\\t%0, %1, %2, lsr #31\";
603
604 output_asm_insn (\"cmp\\t%2, %3\", operands);
605 if (GET_CODE (operands[5]) == AND)
606 {
607 output_asm_insn (\"ite\\t%D4\", operands);
608 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
609 }
610 else if (GET_CODE (operands[5]) == MINUS)
611 {
612 output_asm_insn (\"ite\\t%D4\", operands);
613 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
614 }
615 else if (which_alternative != 0)
616 {
617 output_asm_insn (\"ite\\t%D4\", operands);
618 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
619 }
620 else
621 output_asm_insn (\"it\\t%d4\", operands);
622 return \"%i5%d4\\t%0, %1, #1\";
623 "
624 [(set_attr "conds" "clob")
625 (set_attr "length" "14")]
626 )
627
628 (define_insn "*thumb2_cond_sub"
629 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
630 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
631 (match_operator:SI 4 "arm_comparison_operator"
632 [(match_operand:SI 2 "s_register_operand" "r,r")
633 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
634 (clobber (reg:CC CC_REGNUM))]
635 "TARGET_THUMB2"
636 "*
637 output_asm_insn (\"cmp\\t%2, %3\", operands);
638 if (which_alternative != 0)
639 {
640 output_asm_insn (\"ite\\t%D4\", operands);
641 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
642 }
643 else
644 output_asm_insn (\"it\\t%d4\", operands);
645 return \"sub%d4\\t%0, %1, #1\";
646 "
647 [(set_attr "conds" "clob")
648 (set_attr "length" "10,14")]
649 )
650
651 (define_insn_and_split "*thumb2_negscc"
652 [(set (match_operand:SI 0 "s_register_operand" "=r")
653 (neg:SI (match_operator 3 "arm_comparison_operator"
654 [(match_operand:SI 1 "s_register_operand" "r")
655 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
656 (clobber (reg:CC CC_REGNUM))]
657 "TARGET_THUMB2"
658 "#"
659 "&& reload_completed"
660 [(const_int 0)]
661 {
662 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
663
664 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
665 {
666 /* Emit asr\\t%0, %1, #31 */
667 emit_insn (gen_rtx_SET (VOIDmode,
668 operands[0],
669 gen_rtx_ASHIFTRT (SImode,
670 operands[1],
671 GEN_INT (31))));
672 DONE;
673 }
674 else if (GET_CODE (operands[3]) == NE)
675 {
676 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
677 if (CONST_INT_P (operands[2]))
678 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
679 GEN_INT (- INTVAL (operands[2]))));
680 else
681 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
682
683 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
684 gen_rtx_NE (SImode,
685 cc_reg,
686 const0_rtx),
687 gen_rtx_SET (SImode,
688 operands[0],
689 GEN_INT (~0))));
690 DONE;
691 }
692 else
693 {
694 /* Emit: cmp\\t%1, %2\;ite\\t%D3\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
695 enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
696 enum machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
697 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
698
699 emit_insn (gen_rtx_SET (VOIDmode,
700 cc_reg,
701 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
702 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
703 gen_rtx_fmt_ee (rc,
704 VOIDmode,
705 tmp1,
706 const0_rtx),
707 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
708 rc = GET_CODE (operands[3]);
709 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
710 gen_rtx_fmt_ee (rc,
711 VOIDmode,
712 tmp1,
713 const0_rtx),
714 gen_rtx_SET (VOIDmode,
715 operands[0],
716 GEN_INT (~0))));
717 DONE;
718 }
719 FAIL;
720 }
721 [(set_attr "conds" "clob")
722 (set_attr "length" "14")]
723 )
724
725 (define_insn "*thumb2_movcond"
726 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
727 (if_then_else:SI
728 (match_operator 5 "arm_comparison_operator"
729 [(match_operand:SI 3 "s_register_operand" "r,r,r")
730 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
731 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
732 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
733 (clobber (reg:CC CC_REGNUM))]
734 "TARGET_THUMB2"
735 "*
736 if (GET_CODE (operands[5]) == LT
737 && (operands[4] == const0_rtx))
738 {
739 if (which_alternative != 1 && REG_P (operands[1]))
740 {
741 if (operands[2] == const0_rtx)
742 return \"and\\t%0, %1, %3, asr #31\";
743 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
744 }
745 else if (which_alternative != 0 && REG_P (operands[2]))
746 {
747 if (operands[1] == const0_rtx)
748 return \"bic\\t%0, %2, %3, asr #31\";
749 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
750 }
751 /* The only case that falls through to here is when both ops 1 & 2
752 are constants. */
753 }
754
755 if (GET_CODE (operands[5]) == GE
756 && (operands[4] == const0_rtx))
757 {
758 if (which_alternative != 1 && REG_P (operands[1]))
759 {
760 if (operands[2] == const0_rtx)
761 return \"bic\\t%0, %1, %3, asr #31\";
762 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
763 }
764 else if (which_alternative != 0 && REG_P (operands[2]))
765 {
766 if (operands[1] == const0_rtx)
767 return \"and\\t%0, %2, %3, asr #31\";
768 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
769 }
770 /* The only case that falls through to here is when both ops 1 & 2
771 are constants. */
772 }
773 if (CONST_INT_P (operands[4])
774 && !const_ok_for_arm (INTVAL (operands[4])))
775 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
776 else
777 output_asm_insn (\"cmp\\t%3, %4\", operands);
778 switch (which_alternative)
779 {
780 case 0:
781 output_asm_insn (\"it\\t%D5\", operands);
782 break;
783 case 1:
784 output_asm_insn (\"it\\t%d5\", operands);
785 break;
786 case 2:
787 output_asm_insn (\"ite\\t%d5\", operands);
788 break;
789 default:
790 abort();
791 }
792 if (which_alternative != 0)
793 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
794 if (which_alternative != 1)
795 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
796 return \"\";
797 "
798 [(set_attr "conds" "clob")
799 (set_attr "length" "10,10,14")]
800 )
801
802 ;; Zero and sign extension instructions.
803
804 ;; All supported Thumb2 implementations are armv6, so only that case is
805 ;; provided.
806 (define_insn "*thumb2_extendqisi_v6"
807 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
808 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
809 "TARGET_THUMB2 && arm_arch6"
810 "@
811 sxtb%?\\t%0, %1
812 ldr%(sb%)\\t%0, %1"
813 [(set_attr "type" "simple_alu_shift,load_byte")
814 (set_attr "predicable" "yes")
815 (set_attr "pool_range" "*,4094")
816 (set_attr "neg_pool_range" "*,250")]
817 )
818
819 (define_insn "*thumb2_zero_extendhisi2_v6"
820 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
821 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
822 "TARGET_THUMB2 && arm_arch6"
823 "@
824 uxth%?\\t%0, %1
825 ldr%(h%)\\t%0, %1"
826 [(set_attr "type" "simple_alu_shift,load_byte")
827 (set_attr "predicable" "yes")
828 (set_attr "pool_range" "*,4094")
829 (set_attr "neg_pool_range" "*,250")]
830 )
831
832 (define_insn "thumb2_zero_extendqisi2_v6"
833 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
834 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
835 "TARGET_THUMB2 && arm_arch6"
836 "@
837 uxtb%(%)\\t%0, %1
838 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
839 [(set_attr "type" "simple_alu_shift,load_byte")
840 (set_attr "predicable" "yes")
841 (set_attr "pool_range" "*,4094")
842 (set_attr "neg_pool_range" "*,250")]
843 )
844
845 (define_insn "thumb2_casesi_internal"
846 [(parallel [(set (pc)
847 (if_then_else
848 (leu (match_operand:SI 0 "s_register_operand" "r")
849 (match_operand:SI 1 "arm_rhs_operand" "rI"))
850 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
851 (label_ref (match_operand 2 "" ""))))
852 (label_ref (match_operand 3 "" ""))))
853 (clobber (reg:CC CC_REGNUM))
854 (clobber (match_scratch:SI 4 "=&r"))
855 (use (label_ref (match_dup 2)))])]
856 "TARGET_THUMB2 && !flag_pic"
857 "* return thumb2_output_casesi(operands);"
858 [(set_attr "conds" "clob")
859 (set_attr "length" "16")]
860 )
861
862 (define_insn "thumb2_casesi_internal_pic"
863 [(parallel [(set (pc)
864 (if_then_else
865 (leu (match_operand:SI 0 "s_register_operand" "r")
866 (match_operand:SI 1 "arm_rhs_operand" "rI"))
867 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
868 (label_ref (match_operand 2 "" ""))))
869 (label_ref (match_operand 3 "" ""))))
870 (clobber (reg:CC CC_REGNUM))
871 (clobber (match_scratch:SI 4 "=&r"))
872 (clobber (match_scratch:SI 5 "=r"))
873 (use (label_ref (match_dup 2)))])]
874 "TARGET_THUMB2 && flag_pic"
875 "* return thumb2_output_casesi(operands);"
876 [(set_attr "conds" "clob")
877 (set_attr "length" "20")]
878 )
879
880 (define_insn "*thumb2_return"
881 [(simple_return)]
882 "TARGET_THUMB2"
883 "* return output_return_instruction (const_true_rtx, true, false, true);"
884 [(set_attr "type" "branch")
885 (set_attr "length" "4")]
886 )
887
888 (define_insn_and_split "thumb2_eh_return"
889 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
890 VUNSPEC_EH_RETURN)
891 (clobber (match_scratch:SI 1 "=&r"))]
892 "TARGET_THUMB2"
893 "#"
894 "&& reload_completed"
895 [(const_int 0)]
896 "
897 {
898 thumb_set_return_address (operands[0], operands[1]);
899 DONE;
900 }"
901 )
902
903 (define_insn "*thumb2_alusi3_short"
904 [(set (match_operand:SI 0 "s_register_operand" "=l")
905 (match_operator:SI 3 "thumb_16bit_operator"
906 [(match_operand:SI 1 "s_register_operand" "0")
907 (match_operand:SI 2 "s_register_operand" "l")]))
908 (clobber (reg:CC CC_REGNUM))]
909 "TARGET_THUMB2 && reload_completed
910 && GET_CODE(operands[3]) != PLUS
911 && GET_CODE(operands[3]) != MINUS"
912 "%I3%!\\t%0, %1, %2"
913 [(set_attr "predicable" "yes")
914 (set_attr "length" "2")]
915 )
916
917 (define_insn "*thumb2_shiftsi3_short"
918 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
919 (match_operator:SI 3 "shift_operator"
920 [(match_operand:SI 1 "low_register_operand" "0,l")
921 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
922 (clobber (reg:CC CC_REGNUM))]
923 "TARGET_THUMB2 && reload_completed
924 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
925 || REG_P (operands[2]))"
926 "* return arm_output_shift(operands, 2);"
927 [(set_attr "predicable" "yes")
928 (set_attr "shift" "1")
929 (set_attr "length" "2")
930 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
931 (const_string "alu_shift")
932 (const_string "alu_shift_reg")))]
933 )
934
935 (define_insn "*thumb2_mov<mode>_shortim"
936 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
937 (match_operand:QHSI 1 "const_int_operand" "I"))
938 (clobber (reg:CC CC_REGNUM))]
939 "TARGET_THUMB2 && reload_completed"
940 "mov%!\t%0, %1"
941 [(set_attr "predicable" "yes")
942 (set_attr "length" "2")]
943 )
944
945 (define_insn "*thumb2_addsi_short"
946 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
947 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
948 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
949 (clobber (reg:CC CC_REGNUM))]
950 "TARGET_THUMB2 && reload_completed"
951 "*
952 HOST_WIDE_INT val;
953
954 if (CONST_INT_P (operands[2]))
955 val = INTVAL(operands[2]);
956 else
957 val = 0;
958
959 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
960 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
961 return \"sub%!\\t%0, %1, #%n2\";
962 else
963 return \"add%!\\t%0, %1, %2\";
964 "
965 [(set_attr "predicable" "yes")
966 (set_attr "length" "2")]
967 )
968
969 (define_insn "*thumb2_subsi_short"
970 [(set (match_operand:SI 0 "low_register_operand" "=l")
971 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
972 (match_operand:SI 2 "low_register_operand" "l")))
973 (clobber (reg:CC CC_REGNUM))]
974 "TARGET_THUMB2 && reload_completed"
975 "sub%!\\t%0, %1, %2"
976 [(set_attr "predicable" "yes")
977 (set_attr "length" "2")]
978 )
979
980 (define_peephole2
981 [(set (match_operand:CC 0 "cc_register" "")
982 (compare:CC (match_operand:SI 1 "low_register_operand" "")
983 (match_operand:SI 2 "const_int_operand" "")))]
984 "TARGET_THUMB2
985 && peep2_reg_dead_p (1, operands[1])
986 && satisfies_constraint_Pw (operands[2])"
987 [(parallel
988 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
989 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
990 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
991 )
992
993 (define_peephole2
994 [(match_scratch:SI 3 "l")
995 (set (match_operand:CC 0 "cc_register" "")
996 (compare:CC (match_operand:SI 1 "low_register_operand" "")
997 (match_operand:SI 2 "const_int_operand" "")))]
998 "TARGET_THUMB2
999 && satisfies_constraint_Px (operands[2])"
1000 [(parallel
1001 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1002 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1003 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1004 )
1005
1006 (define_insn "thumb2_addsi3_compare0"
1007 [(set (reg:CC_NOOV CC_REGNUM)
1008 (compare:CC_NOOV
1009 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1010 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1011 (const_int 0)))
1012 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1013 (plus:SI (match_dup 1) (match_dup 2)))]
1014 "TARGET_THUMB2"
1015 "*
1016 HOST_WIDE_INT val;
1017
1018 if (CONST_INT_P (operands[2]))
1019 val = INTVAL (operands[2]);
1020 else
1021 val = 0;
1022
1023 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1024 return \"subs\\t%0, %1, #%n2\";
1025 else
1026 return \"adds\\t%0, %1, %2\";
1027 "
1028 [(set_attr "conds" "set")
1029 (set_attr "length" "2,2,4")]
1030 )
1031
1032 (define_insn "*thumb2_addsi3_compare0_scratch"
1033 [(set (reg:CC_NOOV CC_REGNUM)
1034 (compare:CC_NOOV
1035 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l, r,r")
1036 (match_operand:SI 1 "arm_add_operand" "Pv,l,IL,r"))
1037 (const_int 0)))]
1038 "TARGET_THUMB2"
1039 "*
1040 HOST_WIDE_INT val;
1041
1042 if (CONST_INT_P (operands[1]))
1043 val = INTVAL (operands[1]);
1044 else
1045 val = 0;
1046
1047 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1048 return \"cmp\\t%0, #%n1\";
1049 else
1050 return \"cmn\\t%0, %1\";
1051 "
1052 [(set_attr "conds" "set")
1053 (set_attr "length" "2,2,4,4")
1054 (set_attr "type" "simple_alu_imm,*,simple_alu_imm,*")]
1055 )
1056
1057 (define_insn "*thumb2_mulsi_short"
1058 [(set (match_operand:SI 0 "low_register_operand" "=l")
1059 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1060 (match_operand:SI 2 "low_register_operand" "l")))
1061 (clobber (reg:CC CC_REGNUM))]
1062 "TARGET_THUMB2 && optimize_size && reload_completed"
1063 "mul%!\\t%0, %2, %0"
1064 [(set_attr "predicable" "yes")
1065 (set_attr "length" "2")
1066 (set_attr "insn" "muls")])
1067
1068 (define_insn "*thumb2_mulsi_short_compare0"
1069 [(set (reg:CC_NOOV CC_REGNUM)
1070 (compare:CC_NOOV
1071 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1072 (match_operand:SI 2 "register_operand" "l"))
1073 (const_int 0)))
1074 (set (match_operand:SI 0 "register_operand" "=l")
1075 (mult:SI (match_dup 1) (match_dup 2)))]
1076 "TARGET_THUMB2 && optimize_size"
1077 "muls\\t%0, %2, %0"
1078 [(set_attr "length" "2")
1079 (set_attr "insn" "muls")])
1080
1081 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1082 [(set (reg:CC_NOOV CC_REGNUM)
1083 (compare:CC_NOOV
1084 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1085 (match_operand:SI 2 "register_operand" "l"))
1086 (const_int 0)))
1087 (clobber (match_scratch:SI 0 "=l"))]
1088 "TARGET_THUMB2 && optimize_size"
1089 "muls\\t%0, %2, %0"
1090 [(set_attr "length" "2")
1091 (set_attr "insn" "muls")])
1092
1093 (define_insn "*thumb2_cbz"
1094 [(set (pc) (if_then_else
1095 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1096 (const_int 0))
1097 (label_ref (match_operand 1 "" ""))
1098 (pc)))
1099 (clobber (reg:CC CC_REGNUM))]
1100 "TARGET_THUMB2"
1101 "*
1102 if (get_attr_length (insn) == 2)
1103 return \"cbz\\t%0, %l1\";
1104 else
1105 return \"cmp\\t%0, #0\;beq\\t%l1\";
1106 "
1107 [(set (attr "length")
1108 (if_then_else
1109 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1110 (le (minus (match_dup 1) (pc)) (const_int 128))
1111 (not (match_test "which_alternative")))
1112 (const_int 2)
1113 (const_int 8)))]
1114 )
1115
1116 (define_insn "*thumb2_cbnz"
1117 [(set (pc) (if_then_else
1118 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1119 (const_int 0))
1120 (label_ref (match_operand 1 "" ""))
1121 (pc)))
1122 (clobber (reg:CC CC_REGNUM))]
1123 "TARGET_THUMB2"
1124 "*
1125 if (get_attr_length (insn) == 2)
1126 return \"cbnz\\t%0, %l1\";
1127 else
1128 return \"cmp\\t%0, #0\;bne\\t%l1\";
1129 "
1130 [(set (attr "length")
1131 (if_then_else
1132 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1133 (le (minus (match_dup 1) (pc)) (const_int 128))
1134 (not (match_test "which_alternative")))
1135 (const_int 2)
1136 (const_int 8)))]
1137 )
1138
1139 (define_insn "*thumb2_one_cmplsi2_short"
1140 [(set (match_operand:SI 0 "low_register_operand" "=l")
1141 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1142 (clobber (reg:CC CC_REGNUM))]
1143 "TARGET_THUMB2 && reload_completed"
1144 "mvn%!\t%0, %1"
1145 [(set_attr "predicable" "yes")
1146 (set_attr "length" "2")]
1147 )
1148
1149 (define_insn "*thumb2_negsi2_short"
1150 [(set (match_operand:SI 0 "low_register_operand" "=l")
1151 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1152 (clobber (reg:CC CC_REGNUM))]
1153 "TARGET_THUMB2 && reload_completed"
1154 "neg%!\t%0, %1"
1155 [(set_attr "predicable" "yes")
1156 (set_attr "length" "2")]
1157 )
1158
1159 (define_insn "*orsi_notsi_si"
1160 [(set (match_operand:SI 0 "s_register_operand" "=r")
1161 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1162 (match_operand:SI 1 "s_register_operand" "r")))]
1163 "TARGET_THUMB2"
1164 "orn%?\\t%0, %1, %2"
1165 [(set_attr "predicable" "yes")]
1166 )
1167
1168 (define_insn "*orsi_not_shiftsi_si"
1169 [(set (match_operand:SI 0 "s_register_operand" "=r")
1170 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1171 [(match_operand:SI 2 "s_register_operand" "r")
1172 (match_operand:SI 3 "const_int_operand" "M")]))
1173 (match_operand:SI 1 "s_register_operand" "r")))]
1174 "TARGET_THUMB2"
1175 "orn%?\\t%0, %1, %2%S4"
1176 [(set_attr "predicable" "yes")
1177 (set_attr "shift" "2")
1178 (set_attr "type" "alu_shift")]
1179 )
1180
1181 (define_peephole2
1182 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1183 (compare:CC_NOOV (zero_extract:SI
1184 (match_operand:SI 1 "low_register_operand" "")
1185 (const_int 1)
1186 (match_operand:SI 2 "const_int_operand" ""))
1187 (const_int 0)))
1188 (match_scratch:SI 3 "l")
1189 (set (pc)
1190 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1191 [(match_dup 0) (const_int 0)])
1192 (match_operand 5 "" "")
1193 (match_operand 6 "" "")))]
1194 "TARGET_THUMB2
1195 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)"
1196 [(parallel [(set (match_dup 0)
1197 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1198 (const_int 0)))
1199 (clobber (match_dup 3))])
1200 (set (pc)
1201 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1202 (match_dup 5) (match_dup 6)))]
1203 "
1204 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1205 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1206 VOIDmode, operands[0], const0_rtx);
1207 ")
1208
1209 (define_peephole2
1210 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1211 (compare:CC_NOOV (zero_extract:SI
1212 (match_operand:SI 1 "low_register_operand" "")
1213 (match_operand:SI 2 "const_int_operand" "")
1214 (const_int 0))
1215 (const_int 0)))
1216 (match_scratch:SI 3 "l")
1217 (set (pc)
1218 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1219 [(match_dup 0) (const_int 0)])
1220 (match_operand 5 "" "")
1221 (match_operand 6 "" "")))]
1222 "TARGET_THUMB2
1223 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)"
1224 [(parallel [(set (match_dup 0)
1225 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1226 (const_int 0)))
1227 (clobber (match_dup 3))])
1228 (set (pc)
1229 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1230 (match_dup 5) (match_dup 6)))]
1231 "
1232 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1233 ")
1234
1235 ;; Define the subtract-one-and-jump insns so loop.c
1236 ;; knows what to generate.
1237 (define_expand "doloop_end"
1238 [(use (match_operand 0 "" "")) ; loop pseudo
1239 (use (match_operand 1 "" "")) ; iterations; zero if unknown
1240 (use (match_operand 2 "" "")) ; max iterations
1241 (use (match_operand 3 "" "")) ; loop level
1242 (use (match_operand 4 "" "")) ; label
1243 (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
1244 "TARGET_32BIT"
1245 "
1246 {
1247 /* Currently SMS relies on the do-loop pattern to recognize loops
1248 where (1) the control part consists of all insns defining and/or
1249 using a certain 'count' register and (2) the loop count can be
1250 adjusted by modifying this register prior to the loop.
1251 ??? The possible introduction of a new block to initialize the
1252 new IV can potentially affect branch optimizations. */
1253 if (optimize > 0 && flag_modulo_sched)
1254 {
1255 rtx s0;
1256 rtx bcomp;
1257 rtx loc_ref;
1258 rtx cc_reg;
1259 rtx insn;
1260 rtx cmp;
1261
1262 /* Only use this on innermost loops. */
1263 if (INTVAL (operands[3]) > 1)
1264 FAIL;
1265
1266 if (GET_MODE (operands[0]) != SImode)
1267 FAIL;
1268
1269 s0 = operands [0];
1270 if (TARGET_THUMB2)
1271 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1272 else
1273 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1274
1275 cmp = XVECEXP (PATTERN (insn), 0, 0);
1276 cc_reg = SET_DEST (cmp);
1277 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1278 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
1279 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1280 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1281 loc_ref, pc_rtx)));
1282 DONE;
1283 }else
1284 FAIL;
1285 }")
1286