1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery, LLC.
5 ;; This file is part of GCC.
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)
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>. */
21 ;; Note: Thumb-2 is the variant of the Thumb architecture that adds
22 ;; 32-bit encodings of [almost all of] the Arm instruction set.
23 ;; Some old documents refer to the relatively minor interworking
24 ;; changes made in armv5t as "thumb2". These are considered part
25 ;; the 16-bit Thumb-1 instruction set.
27 ;; 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")))]
35 "bic%?\\t%0, %1, %2%S4"
36 [(set_attr "predicable" "yes")
37 (set_attr "shift" "2")
38 (set_attr "type" "alu_shift")]
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))]
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
52 [(set (reg:CC CC_REGNUM)
53 (compare:CC (match_dup 1) (match_dup 2)))
55 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
59 [(set_attr "conds" "clob")
60 (set_attr "length" "10,10,14")]
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))]
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"
74 [(set (reg:CC CC_REGNUM)
75 (compare:CC (match_dup 1) (match_dup 2)))
77 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
81 [(set_attr "conds" "clob")
82 (set_attr "length" "10,10,14")]
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))]
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"
96 [(set (reg:CC CC_REGNUM)
97 (compare:CC (match_dup 1) (match_dup 2)))
99 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
103 [(set_attr "conds" "clob")
104 (set_attr "length" "10,10,14")]
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))]
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"
118 [(set (reg:CC CC_REGNUM)
119 (compare:CC (match_dup 1) (match_dup 2)))
121 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
125 [(set_attr "conds" "clob")
126 (set_attr "length" "10,10,14")]
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))]
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)
143 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
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]);
150 [(set_attr "conds" "clob")
151 (set_attr "length" "8")]
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))]
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"
165 /* if (which_alternative == 0) */
166 if (REGNO(operands[0]) == REGNO(operands[1]))
168 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
170 emit_insn (gen_rtx_SET (VOIDmode,
172 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
173 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
177 (gen_rtx_SET (VOIDmode,
179 (gen_rtx_MINUS (SImode,
185 emit_insn (gen_rtx_SET (VOIDmode,
188 gen_rtx_ASHIFTRT (SImode,
192 emit_insn (gen_rtx_SET (VOIDmode,
194 gen_rtx_MINUS (SImode,
196 gen_rtx_ASHIFTRT (SImode,
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")]
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))]
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"
220 /* if (which_alternative == 0) */
221 if (REGNO(operands[0]) == REGNO(operands[1]))
223 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
225 emit_insn (gen_rtx_SET (VOIDmode,
227 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
228 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
232 (gen_rtx_SET (VOIDmode,
234 (gen_rtx_MINUS (SImode,
240 emit_insn (gen_rtx_SET (VOIDmode,
243 gen_rtx_ASHIFTRT (SImode,
247 emit_insn (gen_rtx_SET (VOIDmode,
249 gen_rtx_MINUS (SImode,
250 gen_rtx_ASHIFTRT (SImode,
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")]
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,l,r,r,l ,*hk,m,*m")
271 (match_operand:SI 1 "general_operand" "rk,I,Py,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))"
286 [(set_attr "type" "*,simple_alu_imm,simple_alu_imm,simple_alu_imm,*,load1,load1,store1,store1")
287 (set_attr "length" "2,4,2,4,4,4,4,4,4")
288 (set_attr "predicable" "yes")
289 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no")
290 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*")
291 (set_attr "neg_pool_range" "*,*,*,*,*,0,0,*,*")]
294 (define_insn "tls_load_dot_plus_four"
295 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
296 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
298 (match_operand 3 "" "")]
300 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
303 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
304 INTVAL (operands[3]));
305 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
307 [(set_attr "length" "4,4,6,6")]
310 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
311 ;; of the messiness associated with the ARM patterns.
312 (define_insn "*thumb2_movhi_insn"
313 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
314 (match_operand:HI 1 "general_operand" "rI,n,r,m"))]
316 && (register_operand (operands[0], HImode)
317 || register_operand (operands[1], HImode))"
319 mov%?\\t%0, %1\\t%@ movhi
320 movw%?\\t%0, %L1\\t%@ movhi
321 str%(h%)\\t%1, %0\\t%@ movhi
322 ldr%(h%)\\t%0, %1\\t%@ movhi"
323 [(set_attr "type" "*,*,store1,load1")
324 (set_attr "predicable" "yes")
325 (set_attr "pool_range" "*,*,*,4094")
326 (set_attr "neg_pool_range" "*,*,*,250")]
329 (define_insn "*thumb2_cmpsi_neg_shiftsi"
330 [(set (reg:CC CC_REGNUM)
331 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
332 (neg:SI (match_operator:SI 3 "shift_operator"
333 [(match_operand:SI 1 "s_register_operand" "r")
334 (match_operand:SI 2 "const_int_operand" "M")]))))]
337 [(set_attr "conds" "set")
338 (set_attr "shift" "1")
339 (set_attr "type" "alu_shift")]
342 (define_insn_and_split "*thumb2_mov_scc"
343 [(set (match_operand:SI 0 "s_register_operand" "=r")
344 (match_operator:SI 1 "arm_comparison_operator"
345 [(match_operand 2 "cc_register" "") (const_int 0)]))]
347 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
350 (if_then_else:SI (match_dup 1)
354 [(set_attr "conds" "use")
355 (set_attr "length" "10")]
358 (define_insn_and_split "*thumb2_mov_negscc"
359 [(set (match_operand:SI 0 "s_register_operand" "=r")
360 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
361 [(match_operand 2 "cc_register" "") (const_int 0)])))]
363 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
366 (if_then_else:SI (match_dup 1)
370 operands[3] = GEN_INT (~0);
372 [(set_attr "conds" "use")
373 (set_attr "length" "10")]
376 (define_insn_and_split "*thumb2_mov_notscc"
377 [(set (match_operand:SI 0 "s_register_operand" "=r")
378 (not:SI (match_operator:SI 1 "arm_comparison_operator"
379 [(match_operand 2 "cc_register" "") (const_int 0)])))]
381 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
384 (if_then_else:SI (match_dup 1)
388 operands[3] = GEN_INT (~1);
389 operands[4] = GEN_INT (~0);
391 [(set_attr "conds" "use")
392 (set_attr "length" "10")]
395 (define_insn_and_split "*thumb2_movsicc_insn"
396 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,l")
398 (match_operator 3 "arm_comparison_operator"
399 [(match_operand 4 "cc_register" "") (const_int 0)])
400 (match_operand:SI 1 "arm_not_operand" "0 ,Py,0 ,0,rI,K,rI,rI,K ,K,r,lPy")
401 (match_operand:SI 2 "arm_not_operand" "Py,0 ,rI,K,0 ,0,rI,K ,rI,K,r,lPy")))]
404 it\\t%D3\;mov%D3\\t%0, %2
405 it\\t%d3\;mov%d3\\t%0, %1
406 it\\t%D3\;mov%D3\\t%0, %2
407 it\\t%D3\;mvn%D3\\t%0, #%B2
408 it\\t%d3\;mov%d3\\t%0, %1
409 it\\t%d3\;mvn%d3\\t%0, #%B1
416 ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
417 ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
418 ; alt 8: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
419 ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
420 ; alt 10: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
421 ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2"
422 "&& reload_completed"
425 enum rtx_code rev_code;
426 enum machine_mode mode;
429 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
431 gen_rtx_SET (VOIDmode,
434 rev_code = GET_CODE (operands[3]);
435 mode = GET_MODE (operands[4]);
436 if (mode == CCFPmode || mode == CCFPEmode)
437 rev_code = reverse_condition_maybe_unordered (rev_code);
439 rev_code = reverse_condition (rev_code);
441 rev_cond = gen_rtx_fmt_ee (rev_code,
443 gen_rtx_REG (mode, CC_REGNUM),
445 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
447 gen_rtx_SET (VOIDmode,
452 [(set_attr "length" "4,4,6,6,6,6,10,10,10,10,6,6")
453 (set_attr "enabled_for_depr_it" "yes,yes,no,no,no,no,no,no,no,no,yes,yes")
454 (set_attr "conds" "use")]
457 (define_insn "*thumb2_movsfcc_soft_insn"
458 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
459 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
460 [(match_operand 4 "cc_register" "") (const_int 0)])
461 (match_operand:SF 1 "s_register_operand" "0,r")
462 (match_operand:SF 2 "s_register_operand" "r,0")))]
463 "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
465 it\\t%D3\;mov%D3\\t%0, %2
466 it\\t%d3\;mov%d3\\t%0, %1"
467 [(set_attr "length" "6,6")
468 (set_attr "conds" "use")]
471 (define_insn "*call_reg_thumb2"
472 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
473 (match_operand 1 "" ""))
474 (use (match_operand 2 "" ""))
475 (clobber (reg:SI LR_REGNUM))]
478 [(set_attr "type" "call")]
481 (define_insn "*call_value_reg_thumb2"
482 [(set (match_operand 0 "" "")
483 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
484 (match_operand 2 "" "")))
485 (use (match_operand 3 "" ""))
486 (clobber (reg:SI LR_REGNUM))]
489 [(set_attr "type" "call")]
492 (define_insn "*thumb2_indirect_jump"
494 (match_operand:SI 0 "register_operand" "l*r"))]
497 [(set_attr "conds" "clob")]
499 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
500 ;; addresses will have the thumb bit set correctly.
503 (define_insn_and_split "*thumb2_and_scc"
504 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
505 (and:SI (match_operator:SI 1 "arm_comparison_operator"
506 [(match_operand 2 "cc_register" "") (const_int 0)])
507 (match_operand:SI 3 "s_register_operand" "r")))]
509 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
510 "&& reload_completed"
512 (and:SI (match_dup 3) (const_int 1)))
513 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
515 enum machine_mode mode = GET_MODE (operands[2]);
516 enum rtx_code rc = GET_CODE (operands[1]);
518 if (mode == CCFPmode || mode == CCFPEmode)
519 rc = reverse_condition_maybe_unordered (rc);
521 rc = reverse_condition (rc);
522 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
524 [(set_attr "conds" "use")
525 (set (attr "length") (if_then_else (match_test "arm_restrict_it")
530 (define_insn_and_split "*thumb2_ior_scc"
531 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
532 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
533 [(match_operand 2 "cc_register" "") (const_int 0)])
534 (match_operand:SI 3 "s_register_operand" "0,?r")))]
537 it\\t%d1\;orr%d1\\t%0, %3, #1
539 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
541 && REGNO (operands [0]) != REGNO (operands[3])"
542 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
543 (cond_exec (match_dup 4) (set (match_dup 0)
544 (ior:SI (match_dup 3) (const_int 1))))]
546 enum machine_mode mode = GET_MODE (operands[2]);
547 enum rtx_code rc = GET_CODE (operands[1]);
549 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
550 if (mode == CCFPmode || mode == CCFPEmode)
551 rc = reverse_condition_maybe_unordered (rc);
553 rc = reverse_condition (rc);
554 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
556 [(set_attr "conds" "use")
557 (set_attr "length" "6,10")]
560 (define_insn "*thumb2_cond_move"
561 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
562 (if_then_else:SI (match_operator 3 "equality_operator"
563 [(match_operator 4 "arm_comparison_operator"
564 [(match_operand 5 "cc_register" "") (const_int 0)])
566 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
567 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
570 if (GET_CODE (operands[3]) == NE)
572 if (which_alternative != 1)
573 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
574 if (which_alternative != 0)
575 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
578 switch (which_alternative)
581 output_asm_insn (\"it\\t%d4\", operands);
584 output_asm_insn (\"it\\t%D4\", operands);
587 output_asm_insn (\"ite\\t%D4\", operands);
592 if (which_alternative != 0)
593 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
594 if (which_alternative != 1)
595 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
598 [(set_attr "conds" "use")
599 (set_attr "length" "6,6,10")]
602 (define_insn "*thumb2_cond_arith"
603 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
604 (match_operator:SI 5 "shiftable_operator"
605 [(match_operator:SI 4 "arm_comparison_operator"
606 [(match_operand:SI 2 "s_register_operand" "r,r")
607 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
608 (match_operand:SI 1 "s_register_operand" "0,?r")]))
609 (clobber (reg:CC CC_REGNUM))]
612 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
613 return \"%i5\\t%0, %1, %2, lsr #31\";
615 output_asm_insn (\"cmp\\t%2, %3\", operands);
616 if (GET_CODE (operands[5]) == AND)
618 output_asm_insn (\"ite\\t%D4\", operands);
619 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
621 else if (GET_CODE (operands[5]) == MINUS)
623 output_asm_insn (\"ite\\t%D4\", operands);
624 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
626 else if (which_alternative != 0)
628 output_asm_insn (\"ite\\t%D4\", operands);
629 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
632 output_asm_insn (\"it\\t%d4\", operands);
633 return \"%i5%d4\\t%0, %1, #1\";
635 [(set_attr "conds" "clob")
636 (set_attr "length" "14")]
639 (define_insn "*thumb2_cond_sub"
640 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
641 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
642 (match_operator:SI 4 "arm_comparison_operator"
643 [(match_operand:SI 2 "s_register_operand" "r,r")
644 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
645 (clobber (reg:CC CC_REGNUM))]
648 output_asm_insn (\"cmp\\t%2, %3\", operands);
649 if (which_alternative != 0)
651 output_asm_insn (\"ite\\t%D4\", operands);
652 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
655 output_asm_insn (\"it\\t%d4\", operands);
656 return \"sub%d4\\t%0, %1, #1\";
658 [(set_attr "conds" "clob")
659 (set_attr "length" "10,14")]
662 (define_insn_and_split "*thumb2_negscc"
663 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
664 (neg:SI (match_operator 3 "arm_comparison_operator"
665 [(match_operand:SI 1 "s_register_operand" "r")
666 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
667 (clobber (reg:CC CC_REGNUM))]
670 "&& reload_completed"
673 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
675 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
677 /* Emit asr\\t%0, %1, #31 */
678 emit_insn (gen_rtx_SET (VOIDmode,
680 gen_rtx_ASHIFTRT (SImode,
685 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
687 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
688 if (CONST_INT_P (operands[2]))
689 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
690 GEN_INT (- INTVAL (operands[2]))));
692 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
694 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
705 /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
706 enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
707 enum machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
708 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
710 emit_insn (gen_rtx_SET (VOIDmode,
712 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
714 emit_insn (gen_rtx_SET (VOIDmode, operands[0], GEN_INT (~0)));
716 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
721 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
726 [(set_attr "conds" "clob")
727 (set_attr "length" "14")]
730 (define_insn "*thumb2_movcond"
731 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
733 (match_operator 5 "arm_comparison_operator"
734 [(match_operand:SI 3 "s_register_operand" "r,r,r")
735 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
736 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
737 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
738 (clobber (reg:CC CC_REGNUM))]
741 if (GET_CODE (operands[5]) == LT
742 && (operands[4] == const0_rtx))
744 if (which_alternative != 1 && REG_P (operands[1]))
746 if (operands[2] == const0_rtx)
747 return \"and\\t%0, %1, %3, asr #31\";
748 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
750 else if (which_alternative != 0 && REG_P (operands[2]))
752 if (operands[1] == const0_rtx)
753 return \"bic\\t%0, %2, %3, asr #31\";
754 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
756 /* The only case that falls through to here is when both ops 1 & 2
760 if (GET_CODE (operands[5]) == GE
761 && (operands[4] == const0_rtx))
763 if (which_alternative != 1 && REG_P (operands[1]))
765 if (operands[2] == const0_rtx)
766 return \"bic\\t%0, %1, %3, asr #31\";
767 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
769 else if (which_alternative != 0 && REG_P (operands[2]))
771 if (operands[1] == const0_rtx)
772 return \"and\\t%0, %2, %3, asr #31\";
773 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
775 /* The only case that falls through to here is when both ops 1 & 2
778 if (CONST_INT_P (operands[4])
779 && !const_ok_for_arm (INTVAL (operands[4])))
780 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
782 output_asm_insn (\"cmp\\t%3, %4\", operands);
783 switch (which_alternative)
786 output_asm_insn (\"it\\t%D5\", operands);
789 output_asm_insn (\"it\\t%d5\", operands);
792 output_asm_insn (\"ite\\t%d5\", operands);
797 if (which_alternative != 0)
798 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
799 if (which_alternative != 1)
800 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
803 [(set_attr "conds" "clob")
804 (set_attr "length" "10,10,14")]
807 ;; Zero and sign extension instructions.
809 ;; All supported Thumb2 implementations are armv6, so only that case is
811 (define_insn "*thumb2_extendqisi_v6"
812 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
813 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
814 "TARGET_THUMB2 && arm_arch6"
818 [(set_attr "type" "simple_alu_shift,load_byte")
819 (set_attr "predicable" "yes")
820 (set_attr "pool_range" "*,4094")
821 (set_attr "neg_pool_range" "*,250")]
824 (define_insn "*thumb2_zero_extendhisi2_v6"
825 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
826 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
827 "TARGET_THUMB2 && arm_arch6"
831 [(set_attr "type" "simple_alu_shift,load_byte")
832 (set_attr "predicable" "yes")
833 (set_attr "pool_range" "*,4094")
834 (set_attr "neg_pool_range" "*,250")]
837 (define_insn "thumb2_zero_extendqisi2_v6"
838 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
840 "TARGET_THUMB2 && arm_arch6"
843 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
844 [(set_attr "type" "simple_alu_shift,load_byte")
845 (set_attr "predicable" "yes")
846 (set_attr "pool_range" "*,4094")
847 (set_attr "neg_pool_range" "*,250")]
850 (define_insn "thumb2_casesi_internal"
851 [(parallel [(set (pc)
853 (leu (match_operand:SI 0 "s_register_operand" "r")
854 (match_operand:SI 1 "arm_rhs_operand" "rI"))
855 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
856 (label_ref (match_operand 2 "" ""))))
857 (label_ref (match_operand 3 "" ""))))
858 (clobber (reg:CC CC_REGNUM))
859 (clobber (match_scratch:SI 4 "=&r"))
860 (use (label_ref (match_dup 2)))])]
861 "TARGET_THUMB2 && !flag_pic"
862 "* return thumb2_output_casesi(operands);"
863 [(set_attr "conds" "clob")
864 (set_attr "length" "16")]
867 (define_insn "thumb2_casesi_internal_pic"
868 [(parallel [(set (pc)
870 (leu (match_operand:SI 0 "s_register_operand" "r")
871 (match_operand:SI 1 "arm_rhs_operand" "rI"))
872 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
873 (label_ref (match_operand 2 "" ""))))
874 (label_ref (match_operand 3 "" ""))))
875 (clobber (reg:CC CC_REGNUM))
876 (clobber (match_scratch:SI 4 "=&r"))
877 (clobber (match_scratch:SI 5 "=r"))
878 (use (label_ref (match_dup 2)))])]
879 "TARGET_THUMB2 && flag_pic"
880 "* return thumb2_output_casesi(operands);"
881 [(set_attr "conds" "clob")
882 (set_attr "length" "20")]
885 (define_insn "*thumb2_return"
888 "* return output_return_instruction (const_true_rtx, true, false, true);"
889 [(set_attr "type" "branch")
890 (set_attr "length" "4")]
893 (define_insn_and_split "thumb2_eh_return"
894 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
896 (clobber (match_scratch:SI 1 "=&r"))]
899 "&& reload_completed"
903 thumb_set_return_address (operands[0], operands[1]);
908 (define_insn "*thumb2_alusi3_short"
909 [(set (match_operand:SI 0 "s_register_operand" "=l")
910 (match_operator:SI 3 "thumb_16bit_operator"
911 [(match_operand:SI 1 "s_register_operand" "0")
912 (match_operand:SI 2 "s_register_operand" "l")]))
913 (clobber (reg:CC CC_REGNUM))]
914 "TARGET_THUMB2 && reload_completed
915 && GET_CODE(operands[3]) != PLUS
916 && GET_CODE(operands[3]) != MINUS"
918 [(set_attr "predicable" "yes")
919 (set_attr "length" "2")]
922 (define_insn "*thumb2_shiftsi3_short"
923 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
924 (match_operator:SI 3 "shift_operator"
925 [(match_operand:SI 1 "low_register_operand" "0,l")
926 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
927 (clobber (reg:CC CC_REGNUM))]
928 "TARGET_THUMB2 && reload_completed
929 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
930 || REG_P (operands[2]))"
931 "* return arm_output_shift(operands, 2);"
932 [(set_attr "predicable" "yes")
933 (set_attr "shift" "1")
934 (set_attr "length" "2")
935 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
936 (const_string "alu_shift")
937 (const_string "alu_shift_reg")))]
940 (define_insn "*thumb2_mov<mode>_shortim"
941 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
942 (match_operand:QHSI 1 "const_int_operand" "I"))
943 (clobber (reg:CC CC_REGNUM))]
944 "TARGET_THUMB2 && reload_completed"
946 [(set_attr "predicable" "yes")
947 (set_attr "length" "2")]
950 (define_insn "*thumb2_addsi_short"
951 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
952 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
953 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
954 (clobber (reg:CC CC_REGNUM))]
955 "TARGET_THUMB2 && reload_completed"
959 if (CONST_INT_P (operands[2]))
960 val = INTVAL(operands[2]);
964 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
965 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
966 return \"sub%!\\t%0, %1, #%n2\";
968 return \"add%!\\t%0, %1, %2\";
970 [(set_attr "predicable" "yes")
971 (set_attr "length" "2")]
974 (define_insn "*thumb2_subsi_short"
975 [(set (match_operand:SI 0 "low_register_operand" "=l")
976 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
977 (match_operand:SI 2 "low_register_operand" "l")))
978 (clobber (reg:CC CC_REGNUM))]
979 "TARGET_THUMB2 && reload_completed"
981 [(set_attr "predicable" "yes")
982 (set_attr "length" "2")]
986 [(set (match_operand:CC 0 "cc_register" "")
987 (compare:CC (match_operand:SI 1 "low_register_operand" "")
988 (match_operand:SI 2 "const_int_operand" "")))]
990 && peep2_reg_dead_p (1, operands[1])
991 && satisfies_constraint_Pw (operands[2])"
993 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
994 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
995 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
999 [(match_scratch:SI 3 "l")
1000 (set (match_operand:CC 0 "cc_register" "")
1001 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1002 (match_operand:SI 2 "const_int_operand" "")))]
1004 && satisfies_constraint_Px (operands[2])"
1006 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1007 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1008 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1011 (define_insn "thumb2_addsi3_compare0"
1012 [(set (reg:CC_NOOV CC_REGNUM)
1014 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1015 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1017 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1018 (plus:SI (match_dup 1) (match_dup 2)))]
1023 if (CONST_INT_P (operands[2]))
1024 val = INTVAL (operands[2]);
1028 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1029 return \"subs\\t%0, %1, #%n2\";
1031 return \"adds\\t%0, %1, %2\";
1033 [(set_attr "conds" "set")
1034 (set_attr "length" "2,2,4")]
1037 (define_insn "*thumb2_addsi3_compare0_scratch"
1038 [(set (reg:CC_NOOV CC_REGNUM)
1040 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l, r,r")
1041 (match_operand:SI 1 "arm_add_operand" "Pv,l,IL,r"))
1047 if (CONST_INT_P (operands[1]))
1048 val = INTVAL (operands[1]);
1052 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1053 return \"cmp\\t%0, #%n1\";
1055 return \"cmn\\t%0, %1\";
1057 [(set_attr "conds" "set")
1058 (set_attr "length" "2,2,4,4")
1059 (set_attr "type" "simple_alu_imm,*,simple_alu_imm,*")]
1062 (define_insn "*thumb2_mulsi_short"
1063 [(set (match_operand:SI 0 "low_register_operand" "=l")
1064 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1065 (match_operand:SI 2 "low_register_operand" "l")))
1066 (clobber (reg:CC CC_REGNUM))]
1067 "TARGET_THUMB2 && optimize_size && reload_completed"
1068 "mul%!\\t%0, %2, %0"
1069 [(set_attr "predicable" "yes")
1070 (set_attr "length" "2")
1071 (set_attr "type" "muls")])
1073 (define_insn "*thumb2_mulsi_short_compare0"
1074 [(set (reg:CC_NOOV CC_REGNUM)
1076 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1077 (match_operand:SI 2 "register_operand" "l"))
1079 (set (match_operand:SI 0 "register_operand" "=l")
1080 (mult:SI (match_dup 1) (match_dup 2)))]
1081 "TARGET_THUMB2 && optimize_size"
1083 [(set_attr "length" "2")
1084 (set_attr "type" "muls")])
1086 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1087 [(set (reg:CC_NOOV CC_REGNUM)
1089 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1090 (match_operand:SI 2 "register_operand" "l"))
1092 (clobber (match_scratch:SI 0 "=l"))]
1093 "TARGET_THUMB2 && optimize_size"
1095 [(set_attr "length" "2")
1096 (set_attr "type" "muls")])
1098 (define_insn "*thumb2_cbz"
1099 [(set (pc) (if_then_else
1100 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1102 (label_ref (match_operand 1 "" ""))
1104 (clobber (reg:CC CC_REGNUM))]
1107 if (get_attr_length (insn) == 2)
1108 return \"cbz\\t%0, %l1\";
1110 return \"cmp\\t%0, #0\;beq\\t%l1\";
1112 [(set (attr "length")
1114 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1115 (le (minus (match_dup 1) (pc)) (const_int 128))
1116 (not (match_test "which_alternative")))
1121 (define_insn "*thumb2_cbnz"
1122 [(set (pc) (if_then_else
1123 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1125 (label_ref (match_operand 1 "" ""))
1127 (clobber (reg:CC CC_REGNUM))]
1130 if (get_attr_length (insn) == 2)
1131 return \"cbnz\\t%0, %l1\";
1133 return \"cmp\\t%0, #0\;bne\\t%l1\";
1135 [(set (attr "length")
1137 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1138 (le (minus (match_dup 1) (pc)) (const_int 128))
1139 (not (match_test "which_alternative")))
1144 (define_insn "*thumb2_one_cmplsi2_short"
1145 [(set (match_operand:SI 0 "low_register_operand" "=l")
1146 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1147 (clobber (reg:CC CC_REGNUM))]
1148 "TARGET_THUMB2 && reload_completed"
1150 [(set_attr "predicable" "yes")
1151 (set_attr "length" "2")]
1154 (define_insn "*thumb2_negsi2_short"
1155 [(set (match_operand:SI 0 "low_register_operand" "=l")
1156 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1157 (clobber (reg:CC CC_REGNUM))]
1158 "TARGET_THUMB2 && reload_completed"
1160 [(set_attr "predicable" "yes")
1161 (set_attr "length" "2")]
1164 (define_insn "*orsi_notsi_si"
1165 [(set (match_operand:SI 0 "s_register_operand" "=r")
1166 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1167 (match_operand:SI 1 "s_register_operand" "r")))]
1169 "orn%?\\t%0, %1, %2"
1170 [(set_attr "predicable" "yes")]
1173 (define_insn "*orsi_not_shiftsi_si"
1174 [(set (match_operand:SI 0 "s_register_operand" "=r")
1175 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1176 [(match_operand:SI 2 "s_register_operand" "r")
1177 (match_operand:SI 3 "const_int_operand" "M")]))
1178 (match_operand:SI 1 "s_register_operand" "r")))]
1180 "orn%?\\t%0, %1, %2%S4"
1181 [(set_attr "predicable" "yes")
1182 (set_attr "shift" "2")
1183 (set_attr "type" "alu_shift")]
1187 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1188 (compare:CC_NOOV (zero_extract:SI
1189 (match_operand:SI 1 "low_register_operand" "")
1191 (match_operand:SI 2 "const_int_operand" ""))
1193 (match_scratch:SI 3 "l")
1195 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1196 [(match_dup 0) (const_int 0)])
1197 (match_operand 5 "" "")
1198 (match_operand 6 "" "")))]
1200 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)"
1201 [(parallel [(set (match_dup 0)
1202 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1204 (clobber (match_dup 3))])
1206 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1207 (match_dup 5) (match_dup 6)))]
1209 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1210 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1211 VOIDmode, operands[0], const0_rtx);
1215 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1216 (compare:CC_NOOV (zero_extract:SI
1217 (match_operand:SI 1 "low_register_operand" "")
1218 (match_operand:SI 2 "const_int_operand" "")
1221 (match_scratch:SI 3 "l")
1223 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1224 [(match_dup 0) (const_int 0)])
1225 (match_operand 5 "" "")
1226 (match_operand 6 "" "")))]
1228 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)"
1229 [(parallel [(set (match_dup 0)
1230 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1232 (clobber (match_dup 3))])
1234 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1235 (match_dup 5) (match_dup 6)))]
1237 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1240 ;; Define the subtract-one-and-jump insns so loop.c
1241 ;; knows what to generate.
1242 (define_expand "doloop_end"
1243 [(use (match_operand 0 "" "")) ; loop pseudo
1244 (use (match_operand 1 "" "")) ; iterations; zero if unknown
1245 (use (match_operand 2 "" "")) ; max iterations
1246 (use (match_operand 3 "" "")) ; loop level
1247 (use (match_operand 4 "" "")) ; label
1248 (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
1252 /* Currently SMS relies on the do-loop pattern to recognize loops
1253 where (1) the control part consists of all insns defining and/or
1254 using a certain 'count' register and (2) the loop count can be
1255 adjusted by modifying this register prior to the loop.
1256 ??? The possible introduction of a new block to initialize the
1257 new IV can potentially affect branch optimizations. */
1258 if (optimize > 0 && flag_modulo_sched)
1267 /* Only use this on innermost loops. */
1268 if (INTVAL (operands[3]) > 1)
1271 if (GET_MODE (operands[0]) != SImode)
1276 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1278 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1280 cmp = XVECEXP (PATTERN (insn), 0, 0);
1281 cc_reg = SET_DEST (cmp);
1282 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1283 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
1284 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1285 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,