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,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))"
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,*,*")]
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")
295 (match_operand 3 "" "")]
297 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
300 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
301 INTVAL (operands[3]));
302 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
304 [(set_attr "length" "4,4,6,6")]
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"))]
313 && (register_operand (operands[0], HImode)
314 || register_operand (operands[1], HImode))"
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")]
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")]))))]
334 [(set_attr "conds" "set")
335 (set_attr "shift" "1")
336 (set_attr "type" "alu_shift")]
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)]))]
344 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
347 (if_then_else:SI (match_dup 1)
351 [(set_attr "conds" "use")
352 (set_attr "length" "10")]
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)])))]
360 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
363 (if_then_else:SI (match_dup 1)
367 operands[3] = GEN_INT (~0);
369 [(set_attr "conds" "use")
370 (set_attr "length" "10")]
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)])))]
378 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
381 (if_then_else:SI (match_dup 1)
385 operands[3] = GEN_INT (~1);
386 operands[4] = GEN_INT (~0);
388 [(set_attr "conds" "use")
389 (set_attr "length" "10")]
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")
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")))]
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
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"
416 enum rtx_code rev_code;
417 enum machine_mode mode;
420 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
422 gen_rtx_SET (VOIDmode,
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);
430 rev_code = reverse_condition (rev_code);
432 rev_cond = gen_rtx_fmt_ee (rev_code,
434 gen_rtx_REG (mode, CC_REGNUM),
436 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
438 gen_rtx_SET (VOIDmode,
443 [(set_attr "length" "6,6,6,6,10,10,10,10")
444 (set_attr "conds" "use")]
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"
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")]
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))]
468 [(set_attr "type" "call")]
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))]
479 [(set_attr "type" "call")]
482 (define_insn "*thumb2_indirect_jump"
484 (match_operand:SI 0 "register_operand" "l*r"))]
487 [(set_attr "conds" "clob")]
489 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
490 ;; addresses will have the thumb bit set correctly.
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")))]
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))))]
505 enum machine_mode mode = GET_MODE (operands[2]);
506 enum rtx_code rc = GET_CODE (operands[1]);
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);
512 rc = reverse_condition (rc);
513 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
515 [(set_attr "conds" "use")
516 (set_attr "length" "10")]
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")))]
526 it\\t%d1\;orr%d1\\t%0, %3, #1
528 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
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))))]
535 enum machine_mode mode = GET_MODE (operands[2]);
536 enum rtx_code rc = GET_CODE (operands[1]);
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);
542 rc = reverse_condition (rc);
543 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
545 [(set_attr "conds" "use")
546 (set_attr "length" "6,10")]
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)])
555 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
556 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
559 if (GET_CODE (operands[3]) == NE)
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);
567 switch (which_alternative)
570 output_asm_insn (\"it\\t%d4\", operands);
573 output_asm_insn (\"it\\t%D4\", operands);
576 output_asm_insn (\"ite\\t%D4\", operands);
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);
587 [(set_attr "conds" "use")
588 (set_attr "length" "6,6,10")]
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))]
601 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
602 return \"%i5\\t%0, %1, %2, lsr #31\";
604 output_asm_insn (\"cmp\\t%2, %3\", operands);
605 if (GET_CODE (operands[5]) == AND)
607 output_asm_insn (\"ite\\t%D4\", operands);
608 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
610 else if (GET_CODE (operands[5]) == MINUS)
612 output_asm_insn (\"ite\\t%D4\", operands);
613 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
615 else if (which_alternative != 0)
617 output_asm_insn (\"ite\\t%D4\", operands);
618 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
621 output_asm_insn (\"it\\t%d4\", operands);
622 return \"%i5%d4\\t%0, %1, #1\";
624 [(set_attr "conds" "clob")
625 (set_attr "length" "14")]
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))]
637 output_asm_insn (\"cmp\\t%2, %3\", operands);
638 if (which_alternative != 0)
640 output_asm_insn (\"ite\\t%D4\", operands);
641 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
644 output_asm_insn (\"it\\t%d4\", operands);
645 return \"sub%d4\\t%0, %1, #1\";
647 [(set_attr "conds" "clob")
648 (set_attr "length" "10,14")]
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))]
659 "&& reload_completed"
662 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
664 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
666 /* Emit asr\\t%0, %1, #31 */
667 emit_insn (gen_rtx_SET (VOIDmode,
669 gen_rtx_ASHIFTRT (SImode,
674 else if (GET_CODE (operands[3]) == NE)
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]))));
681 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
683 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
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);
699 emit_insn (gen_rtx_SET (VOIDmode,
701 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
702 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
707 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
708 rc = GET_CODE (operands[3]);
709 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
714 gen_rtx_SET (VOIDmode,
721 [(set_attr "conds" "clob")
722 (set_attr "length" "14")]
725 (define_insn "*thumb2_movcond"
726 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
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))]
736 if (GET_CODE (operands[5]) == LT
737 && (operands[4] == const0_rtx))
739 if (which_alternative != 1 && REG_P (operands[1]))
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\";
745 else if (which_alternative != 0 && REG_P (operands[2]))
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\";
751 /* The only case that falls through to here is when both ops 1 & 2
755 if (GET_CODE (operands[5]) == GE
756 && (operands[4] == const0_rtx))
758 if (which_alternative != 1 && REG_P (operands[1]))
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\";
764 else if (which_alternative != 0 && REG_P (operands[2]))
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\";
770 /* The only case that falls through to here is when both ops 1 & 2
773 if (CONST_INT_P (operands[4])
774 && !const_ok_for_arm (INTVAL (operands[4])))
775 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
777 output_asm_insn (\"cmp\\t%3, %4\", operands);
778 switch (which_alternative)
781 output_asm_insn (\"it\\t%D5\", operands);
784 output_asm_insn (\"it\\t%d5\", operands);
787 output_asm_insn (\"ite\\t%d5\", operands);
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);
798 [(set_attr "conds" "clob")
799 (set_attr "length" "10,10,14")]
802 ;; Zero and sign extension instructions.
804 ;; All supported Thumb2 implementations are armv6, so only that case is
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"
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")]
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"
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")]
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"
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")]
845 (define_insn "thumb2_casesi_internal"
846 [(parallel [(set (pc)
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")]
862 (define_insn "thumb2_casesi_internal_pic"
863 [(parallel [(set (pc)
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")]
880 (define_insn "*thumb2_return"
883 "* return output_return_instruction (const_true_rtx, true, false, true);"
884 [(set_attr "type" "branch")
885 (set_attr "length" "4")]
888 (define_insn_and_split "thumb2_eh_return"
889 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
891 (clobber (match_scratch:SI 1 "=&r"))]
894 "&& reload_completed"
898 thumb_set_return_address (operands[0], operands[1]);
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"
913 [(set_attr "predicable" "yes")
914 (set_attr "length" "2")]
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")))]
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"
941 [(set_attr "predicable" "yes")
942 (set_attr "length" "2")]
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"
954 if (CONST_INT_P (operands[2]))
955 val = INTVAL(operands[2]);
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\";
963 return \"add%!\\t%0, %1, %2\";
965 [(set_attr "predicable" "yes")
966 (set_attr "length" "2")]
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"
976 [(set_attr "predicable" "yes")
977 (set_attr "length" "2")]
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" "")))]
985 && peep2_reg_dead_p (1, operands[1])
986 && satisfies_constraint_Pw (operands[2])"
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]));"
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" "")))]
999 && satisfies_constraint_Px (operands[2])"
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]));"
1006 (define_insn "thumb2_addsi3_compare0"
1007 [(set (reg:CC_NOOV CC_REGNUM)
1009 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1010 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1012 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1013 (plus:SI (match_dup 1) (match_dup 2)))]
1018 if (CONST_INT_P (operands[2]))
1019 val = INTVAL (operands[2]);
1023 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1024 return \"subs\\t%0, %1, #%n2\";
1026 return \"adds\\t%0, %1, %2\";
1028 [(set_attr "conds" "set")
1029 (set_attr "length" "2,2,4")]
1032 (define_insn "*thumb2_addsi3_compare0_scratch"
1033 [(set (reg:CC_NOOV CC_REGNUM)
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"))
1042 if (CONST_INT_P (operands[1]))
1043 val = INTVAL (operands[1]);
1047 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1048 return \"cmp\\t%0, #%n1\";
1050 return \"cmn\\t%0, %1\";
1052 [(set_attr "conds" "set")
1053 (set_attr "length" "2,2,4,4")
1054 (set_attr "type" "simple_alu_imm,*,simple_alu_imm,*")]
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 "type" "muls")])
1068 (define_insn "*thumb2_mulsi_short_compare0"
1069 [(set (reg:CC_NOOV CC_REGNUM)
1071 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1072 (match_operand:SI 2 "register_operand" "l"))
1074 (set (match_operand:SI 0 "register_operand" "=l")
1075 (mult:SI (match_dup 1) (match_dup 2)))]
1076 "TARGET_THUMB2 && optimize_size"
1078 [(set_attr "length" "2")
1079 (set_attr "type" "muls")])
1081 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1082 [(set (reg:CC_NOOV CC_REGNUM)
1084 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1085 (match_operand:SI 2 "register_operand" "l"))
1087 (clobber (match_scratch:SI 0 "=l"))]
1088 "TARGET_THUMB2 && optimize_size"
1090 [(set_attr "length" "2")
1091 (set_attr "type" "muls")])
1093 (define_insn "*thumb2_cbz"
1094 [(set (pc) (if_then_else
1095 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1097 (label_ref (match_operand 1 "" ""))
1099 (clobber (reg:CC CC_REGNUM))]
1102 if (get_attr_length (insn) == 2)
1103 return \"cbz\\t%0, %l1\";
1105 return \"cmp\\t%0, #0\;beq\\t%l1\";
1107 [(set (attr "length")
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")))
1116 (define_insn "*thumb2_cbnz"
1117 [(set (pc) (if_then_else
1118 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1120 (label_ref (match_operand 1 "" ""))
1122 (clobber (reg:CC CC_REGNUM))]
1125 if (get_attr_length (insn) == 2)
1126 return \"cbnz\\t%0, %l1\";
1128 return \"cmp\\t%0, #0\;bne\\t%l1\";
1130 [(set (attr "length")
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")))
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"
1145 [(set_attr "predicable" "yes")
1146 (set_attr "length" "2")]
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"
1155 [(set_attr "predicable" "yes")
1156 (set_attr "length" "2")]
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")))]
1164 "orn%?\\t%0, %1, %2"
1165 [(set_attr "predicable" "yes")]
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")))]
1175 "orn%?\\t%0, %1, %2%S4"
1176 [(set_attr "predicable" "yes")
1177 (set_attr "shift" "2")
1178 (set_attr "type" "alu_shift")]
1182 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1183 (compare:CC_NOOV (zero_extract:SI
1184 (match_operand:SI 1 "low_register_operand" "")
1186 (match_operand:SI 2 "const_int_operand" ""))
1188 (match_scratch:SI 3 "l")
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 "" "")))]
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))
1199 (clobber (match_dup 3))])
1201 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1202 (match_dup 5) (match_dup 6)))]
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);
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" "")
1216 (match_scratch:SI 3 "l")
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 "" "")))]
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))
1227 (clobber (match_dup 3))])
1229 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1230 (match_dup 5) (match_dup 6)))]
1232 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
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
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)
1262 /* Only use this on innermost loops. */
1263 if (INTVAL (operands[3]) > 1)
1266 if (GET_MODE (operands[0]) != SImode)
1271 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1273 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
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,