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 (define_insn "*thumb2_incscc"
28 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
29 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
30 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
31 (match_operand:SI 1 "s_register_operand" "0,?r")))]
34 it\\t%d2\;add%d2\\t%0, %1, #1
35 ite\\t%D2\;mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
36 [(set_attr "conds" "use")
37 (set_attr "length" "6,10")]
40 (define_insn "*thumb2_decscc"
41 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
42 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
43 (match_operator:SI 2 "arm_comparison_operator"
44 [(match_operand 3 "cc_register" "") (const_int 0)])))]
47 it\\t%d2\;sub%d2\\t%0, %1, #1
48 ite\\t%D2\;mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
49 [(set_attr "conds" "use")
50 (set_attr "length" "6,10")]
53 ;; Thumb-2 only allows shift by constant on data processing instructions
54 (define_insn "*thumb_andsi_not_shiftsi_si"
55 [(set (match_operand:SI 0 "s_register_operand" "=r")
56 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
57 [(match_operand:SI 2 "s_register_operand" "r")
58 (match_operand:SI 3 "const_int_operand" "M")]))
59 (match_operand:SI 1 "s_register_operand" "r")))]
61 "bic%?\\t%0, %1, %2%S4"
62 [(set_attr "predicable" "yes")
63 (set_attr "shift" "2")
64 (set_attr "type" "alu_shift")]
67 (define_insn "*thumb2_smaxsi3"
68 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
69 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
70 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
71 (clobber (reg:CC CC_REGNUM))]
74 cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
75 cmp\\t%1, %2\;it\\tge\;movge\\t%0, %1
76 cmp\\t%1, %2\;ite\\tge\;movge\\t%0, %1\;movlt\\t%0, %2"
77 [(set_attr "conds" "clob")
78 (set_attr "length" "10,10,14")]
81 (define_insn "*thumb2_sminsi3"
82 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
83 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
84 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
85 (clobber (reg:CC CC_REGNUM))]
88 cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
89 cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %1
90 cmp\\t%1, %2\;ite\\tlt\;movlt\\t%0, %1\;movge\\t%0, %2"
91 [(set_attr "conds" "clob")
92 (set_attr "length" "10,10,14")]
95 (define_insn "*thumb32_umaxsi3"
96 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
97 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
98 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
99 (clobber (reg:CC CC_REGNUM))]
102 cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
103 cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %1
104 cmp\\t%1, %2\;ite\\tcs\;movcs\\t%0, %1\;movcc\\t%0, %2"
105 [(set_attr "conds" "clob")
106 (set_attr "length" "10,10,14")]
109 (define_insn "*thumb2_uminsi3"
110 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
111 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
112 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
113 (clobber (reg:CC CC_REGNUM))]
116 cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
117 cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %1
118 cmp\\t%1, %2\;ite\\tcc\;movcc\\t%0, %1\;movcs\\t%0, %2"
119 [(set_attr "conds" "clob")
120 (set_attr "length" "10,10,14")]
123 ;; Thumb-2 does not have rsc, so use a clever trick with shifter operands.
124 (define_insn "*thumb2_negdi2"
125 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
126 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
127 (clobber (reg:CC CC_REGNUM))]
129 "negs\\t%Q0, %Q1\;sbc\\t%R0, %R1, %R1, lsl #1"
130 [(set_attr "conds" "clob")
131 (set_attr "length" "8")]
134 (define_insn "*thumb2_abssi2"
135 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
136 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
137 (clobber (reg:CC CC_REGNUM))]
140 cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
141 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
142 [(set_attr "conds" "clob,*")
143 (set_attr "shift" "1")
144 (set_attr "predicable" "no, yes")
145 (set_attr "ce_count" "2")
146 (set_attr "length" "10,8")]
149 (define_insn "*thumb2_neg_abssi2"
150 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
151 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
152 (clobber (reg:CC CC_REGNUM))]
155 cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
156 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
157 [(set_attr "conds" "clob,*")
158 (set_attr "shift" "1")
159 (set_attr "predicable" "no, yes")
160 (set_attr "ce_count" "2")
161 (set_attr "length" "10,8")]
164 ;; We have two alternatives here for memory loads (and similarly for stores)
165 ;; to reflect the fact that the permissible constant pool ranges differ
166 ;; between ldr instructions taking low regs and ldr instructions taking high
167 ;; regs. The high register alternatives are not taken into account when
168 ;; choosing register preferences in order to reflect their expense.
169 (define_insn "*thumb2_movsi_insn"
170 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,l ,*hk,m,*m")
171 (match_operand:SI 1 "general_operand" "rk ,I,K,j,mi,*mi,l,*hk"))]
172 "TARGET_THUMB2 && ! TARGET_IWMMXT
173 && !(TARGET_HARD_FLOAT && TARGET_VFP)
174 && ( register_operand (operands[0], SImode)
175 || register_operand (operands[1], SImode))"
185 [(set_attr "type" "*,*,simple_alu_imm,*,load1,load1,store1,store1")
186 (set_attr "predicable" "yes")
187 (set_attr "pool_range" "*,*,*,*,1018,4094,*,*")
188 (set_attr "neg_pool_range" "*,*,*,*,0,0,*,*")]
191 (define_insn "tls_load_dot_plus_four"
192 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
193 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
195 (match_operand 3 "" "")]
197 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
200 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
201 INTVAL (operands[3]));
202 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
204 [(set_attr "length" "4,4,6,6")]
207 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
208 ;; of the messiness associated with the ARM patterns.
209 (define_insn "*thumb2_movhi_insn"
210 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
211 (match_operand:HI 1 "general_operand" "rI,n,r,m"))]
213 && (register_operand (operands[0], HImode)
214 || register_operand (operands[1], HImode))"
216 mov%?\\t%0, %1\\t%@ movhi
217 movw%?\\t%0, %L1\\t%@ movhi
218 str%(h%)\\t%1, %0\\t%@ movhi
219 ldr%(h%)\\t%0, %1\\t%@ movhi"
220 [(set_attr "type" "*,*,store1,load1")
221 (set_attr "predicable" "yes")
222 (set_attr "pool_range" "*,*,*,4094")
223 (set_attr "neg_pool_range" "*,*,*,250")]
226 (define_insn "*thumb2_cmpsi_neg_shiftsi"
227 [(set (reg:CC CC_REGNUM)
228 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
229 (neg:SI (match_operator:SI 3 "shift_operator"
230 [(match_operand:SI 1 "s_register_operand" "r")
231 (match_operand:SI 2 "const_int_operand" "M")]))))]
234 [(set_attr "conds" "set")
235 (set_attr "shift" "1")
236 (set_attr "type" "alu_shift")]
239 (define_insn "*thumb2_mov_scc"
240 [(set (match_operand:SI 0 "s_register_operand" "=r")
241 (match_operator:SI 1 "arm_comparison_operator"
242 [(match_operand 2 "cc_register" "") (const_int 0)]))]
244 "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
245 [(set_attr "conds" "use")
246 (set_attr "length" "10")]
249 (define_insn "*thumb2_mov_negscc"
250 [(set (match_operand:SI 0 "s_register_operand" "=r")
251 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
252 [(match_operand 2 "cc_register" "") (const_int 0)])))]
254 "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
255 [(set_attr "conds" "use")
256 (set_attr "length" "10")]
259 (define_insn "*thumb2_mov_notscc"
260 [(set (match_operand:SI 0 "s_register_operand" "=r")
261 (not:SI (match_operator:SI 1 "arm_comparison_operator"
262 [(match_operand 2 "cc_register" "") (const_int 0)])))]
264 "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
265 [(set_attr "conds" "use")
266 (set_attr "length" "10")]
269 (define_insn "*thumb2_movsicc_insn"
270 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
272 (match_operator 3 "arm_comparison_operator"
273 [(match_operand 4 "cc_register" "") (const_int 0)])
274 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
275 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
278 it\\t%D3\;mov%D3\\t%0, %2
279 it\\t%D3\;mvn%D3\\t%0, #%B2
280 it\\t%d3\;mov%d3\\t%0, %1
281 it\\t%d3\;mvn%d3\\t%0, #%B1
282 ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
283 ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
284 ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
285 ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
286 [(set_attr "length" "6,6,6,6,10,10,10,10")
287 (set_attr "conds" "use")]
290 (define_insn "*thumb2_movsfcc_soft_insn"
291 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
292 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
293 [(match_operand 4 "cc_register" "") (const_int 0)])
294 (match_operand:SF 1 "s_register_operand" "0,r")
295 (match_operand:SF 2 "s_register_operand" "r,0")))]
296 "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
298 it\\t%D3\;mov%D3\\t%0, %2
299 it\\t%d3\;mov%d3\\t%0, %1"
300 [(set_attr "length" "6,6")
301 (set_attr "conds" "use")]
304 (define_insn "*call_reg_thumb2"
305 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
306 (match_operand 1 "" ""))
307 (use (match_operand 2 "" ""))
308 (clobber (reg:SI LR_REGNUM))]
311 [(set_attr "type" "call")]
314 (define_insn "*call_value_reg_thumb2"
315 [(set (match_operand 0 "" "")
316 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
317 (match_operand 2 "" "")))
318 (use (match_operand 3 "" ""))
319 (clobber (reg:SI LR_REGNUM))]
322 [(set_attr "type" "call")]
325 (define_insn "*thumb2_indirect_jump"
327 (match_operand:SI 0 "register_operand" "l*r"))]
330 [(set_attr "conds" "clob")]
332 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
333 ;; addresses will have the thumb bit set correctly.
336 (define_insn "*thumb2_and_scc"
337 [(set (match_operand:SI 0 "s_register_operand" "=r")
338 (and:SI (match_operator:SI 1 "arm_comparison_operator"
339 [(match_operand 3 "cc_register" "") (const_int 0)])
340 (match_operand:SI 2 "s_register_operand" "r")))]
342 "ite\\t%D1\;mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
343 [(set_attr "conds" "use")
344 (set_attr "length" "10")]
347 (define_insn "*thumb2_ior_scc"
348 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
349 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
350 [(match_operand 3 "cc_register" "") (const_int 0)])
351 (match_operand:SI 1 "s_register_operand" "0,?r")))]
354 it\\t%d2\;orr%d2\\t%0, %1, #1
355 ite\\t%D2\;mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
356 [(set_attr "conds" "use")
357 (set_attr "length" "6,10")]
360 (define_insn "*thumb2_cond_move"
361 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
362 (if_then_else:SI (match_operator 3 "equality_operator"
363 [(match_operator 4 "arm_comparison_operator"
364 [(match_operand 5 "cc_register" "") (const_int 0)])
366 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
367 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
370 if (GET_CODE (operands[3]) == NE)
372 if (which_alternative != 1)
373 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
374 if (which_alternative != 0)
375 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
378 switch (which_alternative)
381 output_asm_insn (\"it\\t%d4\", operands);
384 output_asm_insn (\"it\\t%D4\", operands);
387 output_asm_insn (\"ite\\t%D4\", operands);
392 if (which_alternative != 0)
393 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
394 if (which_alternative != 1)
395 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
398 [(set_attr "conds" "use")
399 (set_attr "length" "6,6,10")]
402 (define_insn "*thumb2_cond_arith"
403 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
404 (match_operator:SI 5 "shiftable_operator"
405 [(match_operator:SI 4 "arm_comparison_operator"
406 [(match_operand:SI 2 "s_register_operand" "r,r")
407 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
408 (match_operand:SI 1 "s_register_operand" "0,?r")]))
409 (clobber (reg:CC CC_REGNUM))]
412 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
413 return \"%i5\\t%0, %1, %2, lsr #31\";
415 output_asm_insn (\"cmp\\t%2, %3\", operands);
416 if (GET_CODE (operands[5]) == AND)
418 output_asm_insn (\"ite\\t%D4\", operands);
419 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
421 else if (GET_CODE (operands[5]) == MINUS)
423 output_asm_insn (\"ite\\t%D4\", operands);
424 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
426 else if (which_alternative != 0)
428 output_asm_insn (\"ite\\t%D4\", operands);
429 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
432 output_asm_insn (\"it\\t%d4\", operands);
433 return \"%i5%d4\\t%0, %1, #1\";
435 [(set_attr "conds" "clob")
436 (set_attr "length" "14")]
439 (define_insn "*thumb2_cond_sub"
440 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
441 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
442 (match_operator:SI 4 "arm_comparison_operator"
443 [(match_operand:SI 2 "s_register_operand" "r,r")
444 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
445 (clobber (reg:CC CC_REGNUM))]
448 output_asm_insn (\"cmp\\t%2, %3\", operands);
449 if (which_alternative != 0)
451 output_asm_insn (\"ite\\t%D4\", operands);
452 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
455 output_asm_insn (\"it\\t%d4\", operands);
456 return \"sub%d4\\t%0, %1, #1\";
458 [(set_attr "conds" "clob")
459 (set_attr "length" "10,14")]
462 (define_insn "*thumb2_negscc"
463 [(set (match_operand:SI 0 "s_register_operand" "=r")
464 (neg:SI (match_operator 3 "arm_comparison_operator"
465 [(match_operand:SI 1 "s_register_operand" "r")
466 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
467 (clobber (reg:CC CC_REGNUM))]
470 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
471 return \"asr\\t%0, %1, #31\";
473 if (GET_CODE (operands[3]) == NE)
474 return \"subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0\";
476 output_asm_insn (\"cmp\\t%1, %2\", operands);
477 output_asm_insn (\"ite\\t%D3\", operands);
478 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
479 return \"mvn%d3\\t%0, #0\";
481 [(set_attr "conds" "clob")
482 (set_attr "length" "14")]
485 (define_insn "*thumb2_movcond"
486 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
488 (match_operator 5 "arm_comparison_operator"
489 [(match_operand:SI 3 "s_register_operand" "r,r,r")
490 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
491 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
492 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
493 (clobber (reg:CC CC_REGNUM))]
496 if (GET_CODE (operands[5]) == LT
497 && (operands[4] == const0_rtx))
499 if (which_alternative != 1 && REG_P (operands[1]))
501 if (operands[2] == const0_rtx)
502 return \"and\\t%0, %1, %3, asr #31\";
503 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
505 else if (which_alternative != 0 && REG_P (operands[2]))
507 if (operands[1] == const0_rtx)
508 return \"bic\\t%0, %2, %3, asr #31\";
509 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
511 /* The only case that falls through to here is when both ops 1 & 2
515 if (GET_CODE (operands[5]) == GE
516 && (operands[4] == const0_rtx))
518 if (which_alternative != 1 && REG_P (operands[1]))
520 if (operands[2] == const0_rtx)
521 return \"bic\\t%0, %1, %3, asr #31\";
522 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
524 else if (which_alternative != 0 && REG_P (operands[2]))
526 if (operands[1] == const0_rtx)
527 return \"and\\t%0, %2, %3, asr #31\";
528 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
530 /* The only case that falls through to here is when both ops 1 & 2
533 if (CONST_INT_P (operands[4])
534 && !const_ok_for_arm (INTVAL (operands[4])))
535 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
537 output_asm_insn (\"cmp\\t%3, %4\", operands);
538 switch (which_alternative)
541 output_asm_insn (\"it\\t%D5\", operands);
544 output_asm_insn (\"it\\t%d5\", operands);
547 output_asm_insn (\"ite\\t%d5\", operands);
552 if (which_alternative != 0)
553 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
554 if (which_alternative != 1)
555 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
558 [(set_attr "conds" "clob")
559 (set_attr "length" "10,10,14")]
562 ;; Zero and sign extension instructions.
564 ;; All supported Thumb2 implementations are armv6, so only that case is
566 (define_insn "*thumb2_extendqisi_v6"
567 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
568 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
569 "TARGET_THUMB2 && arm_arch6"
573 [(set_attr "type" "simple_alu_shift,load_byte")
574 (set_attr "predicable" "yes")
575 (set_attr "pool_range" "*,4094")
576 (set_attr "neg_pool_range" "*,250")]
579 (define_insn "*thumb2_zero_extendhisi2_v6"
580 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
581 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
582 "TARGET_THUMB2 && arm_arch6"
586 [(set_attr "type" "simple_alu_shift,load_byte")
587 (set_attr "predicable" "yes")
588 (set_attr "pool_range" "*,4094")
589 (set_attr "neg_pool_range" "*,250")]
592 (define_insn "thumb2_zero_extendqisi2_v6"
593 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
594 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
595 "TARGET_THUMB2 && arm_arch6"
598 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
599 [(set_attr "type" "simple_alu_shift,load_byte")
600 (set_attr "predicable" "yes")
601 (set_attr "pool_range" "*,4094")
602 (set_attr "neg_pool_range" "*,250")]
605 (define_insn "thumb2_casesi_internal"
606 [(parallel [(set (pc)
608 (leu (match_operand:SI 0 "s_register_operand" "r")
609 (match_operand:SI 1 "arm_rhs_operand" "rI"))
610 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
611 (label_ref (match_operand 2 "" ""))))
612 (label_ref (match_operand 3 "" ""))))
613 (clobber (reg:CC CC_REGNUM))
614 (clobber (match_scratch:SI 4 "=&r"))
615 (use (label_ref (match_dup 2)))])]
616 "TARGET_THUMB2 && !flag_pic"
617 "* return thumb2_output_casesi(operands);"
618 [(set_attr "conds" "clob")
619 (set_attr "length" "16")]
622 (define_insn "thumb2_casesi_internal_pic"
623 [(parallel [(set (pc)
625 (leu (match_operand:SI 0 "s_register_operand" "r")
626 (match_operand:SI 1 "arm_rhs_operand" "rI"))
627 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
628 (label_ref (match_operand 2 "" ""))))
629 (label_ref (match_operand 3 "" ""))))
630 (clobber (reg:CC CC_REGNUM))
631 (clobber (match_scratch:SI 4 "=&r"))
632 (clobber (match_scratch:SI 5 "=r"))
633 (use (label_ref (match_dup 2)))])]
634 "TARGET_THUMB2 && flag_pic"
635 "* return thumb2_output_casesi(operands);"
636 [(set_attr "conds" "clob")
637 (set_attr "length" "20")]
640 (define_insn "*thumb2_return"
643 "* return output_return_instruction (const_true_rtx, true, false, true);"
644 [(set_attr "type" "branch")
645 (set_attr "length" "4")]
648 (define_insn_and_split "thumb2_eh_return"
649 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
651 (clobber (match_scratch:SI 1 "=&r"))]
654 "&& reload_completed"
658 thumb_set_return_address (operands[0], operands[1]);
663 (define_insn "*thumb2_alusi3_short"
664 [(set (match_operand:SI 0 "s_register_operand" "=l")
665 (match_operator:SI 3 "thumb_16bit_operator"
666 [(match_operand:SI 1 "s_register_operand" "0")
667 (match_operand:SI 2 "s_register_operand" "l")]))
668 (clobber (reg:CC CC_REGNUM))]
669 "TARGET_THUMB2 && reload_completed
670 && GET_CODE(operands[3]) != PLUS
671 && GET_CODE(operands[3]) != MINUS"
673 [(set_attr "predicable" "yes")
674 (set_attr "length" "2")]
677 (define_insn "*thumb2_shiftsi3_short"
678 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
679 (match_operator:SI 3 "shift_operator"
680 [(match_operand:SI 1 "low_register_operand" "0,l")
681 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
682 (clobber (reg:CC CC_REGNUM))]
683 "TARGET_THUMB2 && reload_completed
684 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
685 || REG_P (operands[2]))"
686 "* return arm_output_shift(operands, 2);"
687 [(set_attr "predicable" "yes")
688 (set_attr "shift" "1")
689 (set_attr "length" "2")
690 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
691 (const_string "alu_shift")
692 (const_string "alu_shift_reg")))]
695 (define_insn "*thumb2_mov<mode>_shortim"
696 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
697 (match_operand:QHSI 1 "const_int_operand" "I"))
698 (clobber (reg:CC CC_REGNUM))]
699 "TARGET_THUMB2 && reload_completed"
701 [(set_attr "predicable" "yes")
702 (set_attr "length" "2")]
705 (define_insn "*thumb2_addsi_short"
706 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
707 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
708 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
709 (clobber (reg:CC CC_REGNUM))]
710 "TARGET_THUMB2 && reload_completed"
714 if (CONST_INT_P (operands[2]))
715 val = INTVAL(operands[2]);
719 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
720 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
721 return \"sub%!\\t%0, %1, #%n2\";
723 return \"add%!\\t%0, %1, %2\";
725 [(set_attr "predicable" "yes")
726 (set_attr "length" "2")]
729 (define_insn "*thumb2_subsi_short"
730 [(set (match_operand:SI 0 "low_register_operand" "=l")
731 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
732 (match_operand:SI 2 "low_register_operand" "l")))
733 (clobber (reg:CC CC_REGNUM))]
734 "TARGET_THUMB2 && reload_completed"
736 [(set_attr "predicable" "yes")
737 (set_attr "length" "2")]
741 [(set (match_operand:CC 0 "cc_register" "")
742 (compare:CC (match_operand:SI 1 "low_register_operand" "")
743 (match_operand:SI 2 "const_int_operand" "")))]
745 && peep2_reg_dead_p (1, operands[1])
746 && satisfies_constraint_Pw (operands[2])"
748 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
749 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
750 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
754 [(match_scratch:SI 3 "l")
755 (set (match_operand:CC 0 "cc_register" "")
756 (compare:CC (match_operand:SI 1 "low_register_operand" "")
757 (match_operand:SI 2 "const_int_operand" "")))]
759 && satisfies_constraint_Px (operands[2])"
761 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
762 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
763 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
766 (define_insn "thumb2_addsi3_compare0"
767 [(set (reg:CC_NOOV CC_REGNUM)
769 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
770 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
772 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
773 (plus:SI (match_dup 1) (match_dup 2)))]
778 if (CONST_INT_P (operands[2]))
779 val = INTVAL (operands[2]);
783 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
784 return \"subs\\t%0, %1, #%n2\";
786 return \"adds\\t%0, %1, %2\";
788 [(set_attr "conds" "set")
789 (set_attr "length" "2,2,4")]
792 (define_insn "*thumb2_addsi3_compare0_scratch"
793 [(set (reg:CC_NOOV CC_REGNUM)
795 (plus:SI (match_operand:SI 0 "s_register_operand" "l,l, r,r")
796 (match_operand:SI 1 "arm_add_operand" "Pv,l,IL,r"))
802 if (CONST_INT_P (operands[1]))
803 val = INTVAL (operands[1]);
807 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
808 return \"cmp\\t%0, #%n1\";
810 return \"cmn\\t%0, %1\";
812 [(set_attr "conds" "set")
813 (set_attr "length" "2,2,4,4")
814 (set_attr "type" "simple_alu_imm,*,simple_alu_imm,*")]
817 (define_insn "*thumb2_mulsi_short"
818 [(set (match_operand:SI 0 "low_register_operand" "=l")
819 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
820 (match_operand:SI 2 "low_register_operand" "l")))
821 (clobber (reg:CC CC_REGNUM))]
822 "TARGET_THUMB2 && optimize_size && reload_completed"
824 [(set_attr "predicable" "yes")
825 (set_attr "length" "2")
826 (set_attr "insn" "muls")])
828 (define_insn "*thumb2_mulsi_short_compare0"
829 [(set (reg:CC_NOOV CC_REGNUM)
831 (mult:SI (match_operand:SI 1 "register_operand" "%0")
832 (match_operand:SI 2 "register_operand" "l"))
834 (set (match_operand:SI 0 "register_operand" "=l")
835 (mult:SI (match_dup 1) (match_dup 2)))]
836 "TARGET_THUMB2 && optimize_size"
838 [(set_attr "length" "2")
839 (set_attr "insn" "muls")])
841 (define_insn "*thumb2_mulsi_short_compare0_scratch"
842 [(set (reg:CC_NOOV CC_REGNUM)
844 (mult:SI (match_operand:SI 1 "register_operand" "%0")
845 (match_operand:SI 2 "register_operand" "l"))
847 (clobber (match_scratch:SI 0 "=l"))]
848 "TARGET_THUMB2 && optimize_size"
850 [(set_attr "length" "2")
851 (set_attr "insn" "muls")])
853 (define_insn "*thumb2_cbz"
854 [(set (pc) (if_then_else
855 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
857 (label_ref (match_operand 1 "" ""))
859 (clobber (reg:CC CC_REGNUM))]
862 if (get_attr_length (insn) == 2)
863 return \"cbz\\t%0, %l1\";
865 return \"cmp\\t%0, #0\;beq\\t%l1\";
867 [(set (attr "length")
869 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
870 (le (minus (match_dup 1) (pc)) (const_int 128))
871 (not (match_test "which_alternative")))
876 (define_insn "*thumb2_cbnz"
877 [(set (pc) (if_then_else
878 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
880 (label_ref (match_operand 1 "" ""))
882 (clobber (reg:CC CC_REGNUM))]
885 if (get_attr_length (insn) == 2)
886 return \"cbnz\\t%0, %l1\";
888 return \"cmp\\t%0, #0\;bne\\t%l1\";
890 [(set (attr "length")
892 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
893 (le (minus (match_dup 1) (pc)) (const_int 128))
894 (not (match_test "which_alternative")))
899 (define_insn "*thumb2_one_cmplsi2_short"
900 [(set (match_operand:SI 0 "low_register_operand" "=l")
901 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
902 (clobber (reg:CC CC_REGNUM))]
903 "TARGET_THUMB2 && reload_completed"
905 [(set_attr "predicable" "yes")
906 (set_attr "length" "2")]
909 (define_insn "*thumb2_negsi2_short"
910 [(set (match_operand:SI 0 "low_register_operand" "=l")
911 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
912 (clobber (reg:CC CC_REGNUM))]
913 "TARGET_THUMB2 && reload_completed"
915 [(set_attr "predicable" "yes")
916 (set_attr "length" "2")]
919 (define_insn "*orsi_notsi_si"
920 [(set (match_operand:SI 0 "s_register_operand" "=r")
921 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
922 (match_operand:SI 1 "s_register_operand" "r")))]
925 [(set_attr "predicable" "yes")]
928 (define_insn "*orsi_not_shiftsi_si"
929 [(set (match_operand:SI 0 "s_register_operand" "=r")
930 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
931 [(match_operand:SI 2 "s_register_operand" "r")
932 (match_operand:SI 3 "const_int_operand" "M")]))
933 (match_operand:SI 1 "s_register_operand" "r")))]
935 "orn%?\\t%0, %1, %2%S4"
936 [(set_attr "predicable" "yes")
937 (set_attr "shift" "2")
938 (set_attr "type" "alu_shift")]
942 [(set (match_operand:CC_NOOV 0 "cc_register" "")
943 (compare:CC_NOOV (zero_extract:SI
944 (match_operand:SI 1 "low_register_operand" "")
946 (match_operand:SI 2 "const_int_operand" ""))
948 (match_scratch:SI 3 "l")
950 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
951 [(match_dup 0) (const_int 0)])
952 (match_operand 5 "" "")
953 (match_operand 6 "" "")))]
955 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)"
956 [(parallel [(set (match_dup 0)
957 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
959 (clobber (match_dup 3))])
961 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
962 (match_dup 5) (match_dup 6)))]
964 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
965 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
966 VOIDmode, operands[0], const0_rtx);
970 [(set (match_operand:CC_NOOV 0 "cc_register" "")
971 (compare:CC_NOOV (zero_extract:SI
972 (match_operand:SI 1 "low_register_operand" "")
973 (match_operand:SI 2 "const_int_operand" "")
976 (match_scratch:SI 3 "l")
978 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
979 [(match_dup 0) (const_int 0)])
980 (match_operand 5 "" "")
981 (match_operand 6 "" "")))]
983 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)"
984 [(parallel [(set (match_dup 0)
985 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
987 (clobber (match_dup 3))])
989 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
990 (match_dup 5) (match_dup 6)))]
992 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
995 ;; Define the subtract-one-and-jump insns so loop.c
996 ;; knows what to generate.
997 (define_expand "doloop_end"
998 [(use (match_operand 0 "" "")) ; loop pseudo
999 (use (match_operand 1 "" "")) ; iterations; zero if unknown
1000 (use (match_operand 2 "" "")) ; max iterations
1001 (use (match_operand 3 "" "")) ; loop level
1002 (use (match_operand 4 "" "")) ; label
1003 (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0
1007 /* Currently SMS relies on the do-loop pattern to recognize loops
1008 where (1) the control part consists of all insns defining and/or
1009 using a certain 'count' register and (2) the loop count can be
1010 adjusted by modifying this register prior to the loop.
1011 ??? The possible introduction of a new block to initialize the
1012 new IV can potentially affect branch optimizations. */
1013 if (optimize > 0 && flag_modulo_sched)
1022 /* Only use this on innermost loops. */
1023 if (INTVAL (operands[3]) > 1)
1026 if (GET_MODE (operands[0]) != SImode)
1031 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1033 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1035 cmp = XVECEXP (PATTERN (insn), 0, 0);
1036 cc_reg = SET_DEST (cmp);
1037 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1038 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
1039 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1040 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,