]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/thumb2.md
arm.md (attribute "type"): Rename "simple_alu_imm" to "arlo_imm".
[thirdparty/gcc.git] / gcc / config / arm / thumb2.md
1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery, LLC.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>. */
20
21 ;; Note: Thumb-2 is the variant of the Thumb architecture that adds
22 ;; 32-bit encodings of [almost all of] the Arm instruction set.
23 ;; Some old documents refer to the relatively minor interworking
24 ;; changes made in armv5t as "thumb2". These are considered part
25 ;; the 16-bit Thumb-1 instruction set.
26
27 ;; Thumb-2 only allows shift by constant on data processing instructions
28 (define_insn "*thumb_andsi_not_shiftsi_si"
29 [(set (match_operand:SI 0 "s_register_operand" "=r")
30 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
31 [(match_operand:SI 2 "s_register_operand" "r")
32 (match_operand:SI 3 "const_int_operand" "M")]))
33 (match_operand:SI 1 "s_register_operand" "r")))]
34 "TARGET_THUMB2"
35 "bic%?\\t%0, %1, %2%S4"
36 [(set_attr "predicable" "yes")
37 (set_attr "shift" "2")
38 (set_attr "type" "arlo_shift")]
39 )
40
41 (define_insn_and_split "*thumb2_smaxsi3"
42 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
43 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
44 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
45 (clobber (reg:CC CC_REGNUM))]
46 "TARGET_THUMB2"
47 "#"
48 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
49 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %1
50 ; cmp\\t%1, %2\;ite\\tge\;movge\\t%0, %1\;movlt\\t%0, %2
51 "TARGET_THUMB2"
52 [(set (reg:CC CC_REGNUM)
53 (compare:CC (match_dup 1) (match_dup 2)))
54 (set (match_dup 0)
55 (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
56 (match_dup 1)
57 (match_dup 2)))]
58 ""
59 [(set_attr "conds" "clob")
60 (set_attr "length" "10,10,14")]
61 )
62
63 (define_insn_and_split "*thumb2_sminsi3"
64 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
65 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
66 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
67 (clobber (reg:CC CC_REGNUM))]
68 "TARGET_THUMB2"
69 "#"
70 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
71 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %1
72 ; cmp\\t%1, %2\;ite\\tlt\;movlt\\t%0, %1\;movge\\t%0, %2"
73 "TARGET_THUMB2"
74 [(set (reg:CC CC_REGNUM)
75 (compare:CC (match_dup 1) (match_dup 2)))
76 (set (match_dup 0)
77 (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
78 (match_dup 1)
79 (match_dup 2)))]
80 ""
81 [(set_attr "conds" "clob")
82 (set_attr "length" "10,10,14")]
83 )
84
85 (define_insn_and_split "*thumb32_umaxsi3"
86 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
87 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
88 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
89 (clobber (reg:CC CC_REGNUM))]
90 "TARGET_THUMB2"
91 "#"
92 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
93 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %1
94 ; cmp\\t%1, %2\;ite\\tcs\;movcs\\t%0, %1\;movcc\\t%0, %2"
95 "TARGET_THUMB2"
96 [(set (reg:CC CC_REGNUM)
97 (compare:CC (match_dup 1) (match_dup 2)))
98 (set (match_dup 0)
99 (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
100 (match_dup 1)
101 (match_dup 2)))]
102 ""
103 [(set_attr "conds" "clob")
104 (set_attr "length" "10,10,14")]
105 )
106
107 (define_insn_and_split "*thumb2_uminsi3"
108 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
109 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
110 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
111 (clobber (reg:CC CC_REGNUM))]
112 "TARGET_THUMB2"
113 "#"
114 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
115 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %1
116 ; cmp\\t%1, %2\;ite\\tcc\;movcc\\t%0, %1\;movcs\\t%0, %2"
117 "TARGET_THUMB2"
118 [(set (reg:CC CC_REGNUM)
119 (compare:CC (match_dup 1) (match_dup 2)))
120 (set (match_dup 0)
121 (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
122 (match_dup 1)
123 (match_dup 2)))]
124 ""
125 [(set_attr "conds" "clob")
126 (set_attr "length" "10,10,14")]
127 )
128
129 ;; Thumb-2 does not have rsc, so use a clever trick with shifter operands.
130 (define_insn_and_split "*thumb2_negdi2"
131 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
132 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
133 (clobber (reg:CC CC_REGNUM))]
134 "TARGET_THUMB2"
135 "#" ; negs\\t%Q0, %Q1\;sbc\\t%R0, %R1, %R1, lsl #1
136 "&& reload_completed"
137 [(parallel [(set (reg:CC CC_REGNUM)
138 (compare:CC (const_int 0) (match_dup 1)))
139 (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
140 (set (match_dup 2) (minus:SI (minus:SI (match_dup 3)
141 (ashift:SI (match_dup 3)
142 (const_int 1)))
143 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
144 {
145 operands[2] = gen_highpart (SImode, operands[0]);
146 operands[0] = gen_lowpart (SImode, operands[0]);
147 operands[3] = gen_highpart (SImode, operands[1]);
148 operands[1] = gen_lowpart (SImode, operands[1]);
149 }
150 [(set_attr "conds" "clob")
151 (set_attr "length" "8")]
152 )
153
154 (define_insn_and_split "*thumb2_abssi2"
155 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
156 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
157 (clobber (reg:CC CC_REGNUM))]
158 "TARGET_THUMB2"
159 "#"
160 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
161 ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
162 "&& reload_completed"
163 [(const_int 0)]
164 {
165 /* if (which_alternative == 0) */
166 if (REGNO(operands[0]) == REGNO(operands[1]))
167 {
168 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
169
170 emit_insn (gen_rtx_SET (VOIDmode,
171 cc_reg,
172 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
173 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
174 (gen_rtx_LT (SImode,
175 cc_reg,
176 const0_rtx)),
177 (gen_rtx_SET (VOIDmode,
178 operands[0],
179 (gen_rtx_MINUS (SImode,
180 const0_rtx,
181 operands[1]))))));
182 }
183 else
184 {
185 emit_insn (gen_rtx_SET (VOIDmode,
186 operands[0],
187 gen_rtx_XOR (SImode,
188 gen_rtx_ASHIFTRT (SImode,
189 operands[1],
190 GEN_INT (31)),
191 operands[1])));
192 emit_insn (gen_rtx_SET (VOIDmode,
193 operands[0],
194 gen_rtx_MINUS (SImode,
195 operands[0],
196 gen_rtx_ASHIFTRT (SImode,
197 operands[1],
198 GEN_INT (31)))));
199 }
200 DONE;
201 }
202 [(set_attr "conds" "clob,*")
203 (set_attr "shift" "1")
204 (set_attr "predicable" "no, yes")
205 (set_attr "ce_count" "2")
206 (set_attr "length" "10,8")]
207 )
208
209 (define_insn_and_split "*thumb2_neg_abssi2"
210 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
211 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
212 (clobber (reg:CC CC_REGNUM))]
213 "TARGET_THUMB2"
214 "#"
215 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
216 ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
217 "&& reload_completed"
218 [(const_int 0)]
219 {
220 /* if (which_alternative == 0) */
221 if (REGNO(operands[0]) == REGNO(operands[1]))
222 {
223 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
224
225 emit_insn (gen_rtx_SET (VOIDmode,
226 cc_reg,
227 gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
228 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
229 (gen_rtx_GT (SImode,
230 cc_reg,
231 const0_rtx)),
232 (gen_rtx_SET (VOIDmode,
233 operands[0],
234 (gen_rtx_MINUS (SImode,
235 const0_rtx,
236 operands[1]))))));
237 }
238 else
239 {
240 emit_insn (gen_rtx_SET (VOIDmode,
241 operands[0],
242 gen_rtx_XOR (SImode,
243 gen_rtx_ASHIFTRT (SImode,
244 operands[1],
245 GEN_INT (31)),
246 operands[1])));
247 emit_insn (gen_rtx_SET (VOIDmode,
248 operands[0],
249 gen_rtx_MINUS (SImode,
250 gen_rtx_ASHIFTRT (SImode,
251 operands[1],
252 GEN_INT (31)),
253 operands[0])));
254 }
255 DONE;
256 }
257 [(set_attr "conds" "clob,*")
258 (set_attr "shift" "1")
259 (set_attr "predicable" "no, yes")
260 (set_attr "ce_count" "2")
261 (set_attr "length" "10,8")]
262 )
263
264 ;; We have two alternatives here for memory loads (and similarly for stores)
265 ;; to reflect the fact that the permissible constant pool ranges differ
266 ;; between ldr instructions taking low regs and ldr instructions taking high
267 ;; regs. The high register alternatives are not taken into account when
268 ;; choosing register preferences in order to reflect their expense.
269 (define_insn "*thumb2_movsi_insn"
270 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,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))"
276 "@
277 mov%?\\t%0, %1
278 mov%?\\t%0, %1
279 mov%?\\t%0, %1
280 mvn%?\\t%0, #%B1
281 movw%?\\t%0, %1
282 ldr%?\\t%0, %1
283 ldr%?\\t%0, %1
284 str%?\\t%1, %0
285 str%?\\t%1, %0"
286 [(set_attr "type" "*,arlo_imm,arlo_imm,arlo_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,*,*")]
292 )
293
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")
297 (const_int 4)
298 (match_operand 3 "" "")]
299 UNSPEC_PIC_BASE)))
300 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
301 "TARGET_THUMB2"
302 "*
303 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
304 INTVAL (operands[3]));
305 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
306 "
307 [(set_attr "length" "4,4,6,6")]
308 )
309
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"))]
315 "TARGET_THUMB2
316 && (register_operand (operands[0], HImode)
317 || register_operand (operands[1], HImode))"
318 "@
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")]
327 )
328
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")]))))]
335 "TARGET_THUMB2"
336 "cmn%?\\t%0, %1%S3"
337 [(set_attr "conds" "set")
338 (set_attr "shift" "1")
339 (set_attr "type" "arlo_shift")]
340 )
341
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)]))]
346 "TARGET_THUMB2"
347 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
348 "TARGET_THUMB2"
349 [(set (match_dup 0)
350 (if_then_else:SI (match_dup 1)
351 (const_int 1)
352 (const_int 0)))]
353 ""
354 [(set_attr "conds" "use")
355 (set_attr "length" "10")]
356 )
357
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)])))]
362 "TARGET_THUMB2"
363 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
364 "TARGET_THUMB2"
365 [(set (match_dup 0)
366 (if_then_else:SI (match_dup 1)
367 (match_dup 3)
368 (const_int 0)))]
369 {
370 operands[3] = GEN_INT (~0);
371 }
372 [(set_attr "conds" "use")
373 (set_attr "length" "10")]
374 )
375
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)])))]
380 "TARGET_THUMB2"
381 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
382 "TARGET_THUMB2"
383 [(set (match_dup 0)
384 (if_then_else:SI (match_dup 1)
385 (match_dup 3)
386 (match_dup 4)))]
387 {
388 operands[3] = GEN_INT (~1);
389 operands[4] = GEN_INT (~0);
390 }
391 [(set_attr "conds" "use")
392 (set_attr "length" "10")]
393 )
394
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")
397 (if_then_else:SI
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")))]
402 "TARGET_THUMB2"
403 "@
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
410 #
411 #
412 #
413 #
414 #
415 #"
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"
423 [(const_int 0)]
424 {
425 enum rtx_code rev_code;
426 enum machine_mode mode;
427 rtx rev_cond;
428
429 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
430 operands[3],
431 gen_rtx_SET (VOIDmode,
432 operands[0],
433 operands[1])));
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);
438 else
439 rev_code = reverse_condition (rev_code);
440
441 rev_cond = gen_rtx_fmt_ee (rev_code,
442 VOIDmode,
443 gen_rtx_REG (mode, CC_REGNUM),
444 const0_rtx);
445 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
446 rev_cond,
447 gen_rtx_SET (VOIDmode,
448 operands[0],
449 operands[2])));
450 DONE;
451 }
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")]
455 )
456
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"
464 "@
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")]
469 )
470
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))]
476 "TARGET_THUMB2"
477 "blx%?\\t%0"
478 [(set_attr "type" "call")]
479 )
480
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))]
487 "TARGET_THUMB2"
488 "blx\\t%1"
489 [(set_attr "type" "call")]
490 )
491
492 (define_insn "*thumb2_indirect_jump"
493 [(set (pc)
494 (match_operand:SI 0 "register_operand" "l*r"))]
495 "TARGET_THUMB2"
496 "bx\\t%0"
497 [(set_attr "conds" "clob")]
498 )
499 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
500 ;; addresses will have the thumb bit set correctly.
501
502
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")))]
508 "TARGET_THUMB2"
509 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
510 "&& reload_completed"
511 [(set (match_dup 0)
512 (and:SI (match_dup 3) (const_int 1)))
513 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
514 {
515 enum machine_mode mode = GET_MODE (operands[2]);
516 enum rtx_code rc = GET_CODE (operands[1]);
517
518 if (mode == CCFPmode || mode == CCFPEmode)
519 rc = reverse_condition_maybe_unordered (rc);
520 else
521 rc = reverse_condition (rc);
522 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
523 }
524 [(set_attr "conds" "use")
525 (set (attr "length") (if_then_else (match_test "arm_restrict_it")
526 (const_int 8)
527 (const_int 10)))]
528 )
529
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")))]
535 "TARGET_THUMB2"
536 "@
537 it\\t%d1\;orr%d1\\t%0, %3, #1
538 #"
539 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
540 "&& reload_completed
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))))]
545 {
546 enum machine_mode mode = GET_MODE (operands[2]);
547 enum rtx_code rc = GET_CODE (operands[1]);
548
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);
552 else
553 rc = reverse_condition (rc);
554 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
555 }
556 [(set_attr "conds" "use")
557 (set_attr "length" "6,10")]
558 )
559
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)])
565 (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")))]
568 "TARGET_THUMB2"
569 "*
570 if (GET_CODE (operands[3]) == NE)
571 {
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);
576 return \"\";
577 }
578 switch (which_alternative)
579 {
580 case 0:
581 output_asm_insn (\"it\\t%d4\", operands);
582 break;
583 case 1:
584 output_asm_insn (\"it\\t%D4\", operands);
585 break;
586 case 2:
587 output_asm_insn (\"ite\\t%D4\", operands);
588 break;
589 default:
590 abort();
591 }
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);
596 return \"\";
597 "
598 [(set_attr "conds" "use")
599 (set_attr "length" "6,6,10")]
600 )
601
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))]
610 "TARGET_THUMB2"
611 "*
612 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
613 return \"%i5\\t%0, %1, %2, lsr #31\";
614
615 output_asm_insn (\"cmp\\t%2, %3\", operands);
616 if (GET_CODE (operands[5]) == AND)
617 {
618 output_asm_insn (\"ite\\t%D4\", operands);
619 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
620 }
621 else if (GET_CODE (operands[5]) == MINUS)
622 {
623 output_asm_insn (\"ite\\t%D4\", operands);
624 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
625 }
626 else if (which_alternative != 0)
627 {
628 output_asm_insn (\"ite\\t%D4\", operands);
629 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
630 }
631 else
632 output_asm_insn (\"it\\t%d4\", operands);
633 return \"%i5%d4\\t%0, %1, #1\";
634 "
635 [(set_attr "conds" "clob")
636 (set_attr "length" "14")]
637 )
638
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))]
646 "TARGET_THUMB2"
647 "*
648 output_asm_insn (\"cmp\\t%2, %3\", operands);
649 if (which_alternative != 0)
650 {
651 output_asm_insn (\"ite\\t%D4\", operands);
652 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
653 }
654 else
655 output_asm_insn (\"it\\t%d4\", operands);
656 return \"sub%d4\\t%0, %1, #1\";
657 "
658 [(set_attr "conds" "clob")
659 (set_attr "length" "10,14")]
660 )
661
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))]
668 "TARGET_THUMB2"
669 "#"
670 "&& reload_completed"
671 [(const_int 0)]
672 {
673 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
674
675 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
676 {
677 /* Emit asr\\t%0, %1, #31 */
678 emit_insn (gen_rtx_SET (VOIDmode,
679 operands[0],
680 gen_rtx_ASHIFTRT (SImode,
681 operands[1],
682 GEN_INT (31))));
683 DONE;
684 }
685 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
686 {
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]))));
691 else
692 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
693
694 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
695 gen_rtx_NE (SImode,
696 cc_reg,
697 const0_rtx),
698 gen_rtx_SET (SImode,
699 operands[0],
700 GEN_INT (~0))));
701 DONE;
702 }
703 else
704 {
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);
709
710 emit_insn (gen_rtx_SET (VOIDmode,
711 cc_reg,
712 gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
713
714 emit_insn (gen_rtx_SET (VOIDmode, operands[0], GEN_INT (~0)));
715
716 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
717 gen_rtx_fmt_ee (rc,
718 VOIDmode,
719 tmp1,
720 const0_rtx),
721 gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
722 DONE;
723 }
724 FAIL;
725 }
726 [(set_attr "conds" "clob")
727 (set_attr "length" "14")]
728 )
729
730 (define_insn "*thumb2_movcond"
731 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
732 (if_then_else:SI
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))]
739 "TARGET_THUMB2"
740 "*
741 if (GET_CODE (operands[5]) == LT
742 && (operands[4] == const0_rtx))
743 {
744 if (which_alternative != 1 && REG_P (operands[1]))
745 {
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\";
749 }
750 else if (which_alternative != 0 && REG_P (operands[2]))
751 {
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\";
755 }
756 /* The only case that falls through to here is when both ops 1 & 2
757 are constants. */
758 }
759
760 if (GET_CODE (operands[5]) == GE
761 && (operands[4] == const0_rtx))
762 {
763 if (which_alternative != 1 && REG_P (operands[1]))
764 {
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\";
768 }
769 else if (which_alternative != 0 && REG_P (operands[2]))
770 {
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\";
774 }
775 /* The only case that falls through to here is when both ops 1 & 2
776 are constants. */
777 }
778 if (CONST_INT_P (operands[4])
779 && !const_ok_for_arm (INTVAL (operands[4])))
780 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
781 else
782 output_asm_insn (\"cmp\\t%3, %4\", operands);
783 switch (which_alternative)
784 {
785 case 0:
786 output_asm_insn (\"it\\t%D5\", operands);
787 break;
788 case 1:
789 output_asm_insn (\"it\\t%d5\", operands);
790 break;
791 case 2:
792 output_asm_insn (\"ite\\t%d5\", operands);
793 break;
794 default:
795 abort();
796 }
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);
801 return \"\";
802 "
803 [(set_attr "conds" "clob")
804 (set_attr "length" "10,10,14")]
805 )
806
807 ;; Zero and sign extension instructions.
808
809 ;; All supported Thumb2 implementations are armv6, so only that case is
810 ;; provided.
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"
815 "@
816 sxtb%?\\t%0, %1
817 ldr%(sb%)\\t%0, %1"
818 [(set_attr "type" "extend,load_byte")
819 (set_attr "predicable" "yes")
820 (set_attr "pool_range" "*,4094")
821 (set_attr "neg_pool_range" "*,250")]
822 )
823
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"
828 "@
829 uxth%?\\t%0, %1
830 ldr%(h%)\\t%0, %1"
831 [(set_attr "type" "extend,load_byte")
832 (set_attr "predicable" "yes")
833 (set_attr "pool_range" "*,4094")
834 (set_attr "neg_pool_range" "*,250")]
835 )
836
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"
841 "@
842 uxtb%(%)\\t%0, %1
843 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
844 [(set_attr "type" "extend,load_byte")
845 (set_attr "predicable" "yes")
846 (set_attr "pool_range" "*,4094")
847 (set_attr "neg_pool_range" "*,250")]
848 )
849
850 (define_insn "thumb2_casesi_internal"
851 [(parallel [(set (pc)
852 (if_then_else
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")]
865 )
866
867 (define_insn "thumb2_casesi_internal_pic"
868 [(parallel [(set (pc)
869 (if_then_else
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")]
883 )
884
885 (define_insn "*thumb2_return"
886 [(simple_return)]
887 "TARGET_THUMB2"
888 "* return output_return_instruction (const_true_rtx, true, false, true);"
889 [(set_attr "type" "branch")
890 (set_attr "length" "4")]
891 )
892
893 (define_insn_and_split "thumb2_eh_return"
894 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
895 VUNSPEC_EH_RETURN)
896 (clobber (match_scratch:SI 1 "=&r"))]
897 "TARGET_THUMB2"
898 "#"
899 "&& reload_completed"
900 [(const_int 0)]
901 "
902 {
903 thumb_set_return_address (operands[0], operands[1]);
904 DONE;
905 }"
906 )
907
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"
917 "%I3%!\\t%0, %1, %2"
918 [(set_attr "predicable" "yes")
919 (set_attr "length" "2")]
920 )
921
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 "arlo_shift")
937 (const_string "arlo_shift_reg")))]
938 )
939
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"
945 "mov%!\t%0, %1"
946 [(set_attr "predicable" "yes")
947 (set_attr "length" "2")]
948 )
949
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"
956 "*
957 HOST_WIDE_INT val;
958
959 if (CONST_INT_P (operands[2]))
960 val = INTVAL(operands[2]);
961 else
962 val = 0;
963
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\";
967 else
968 return \"add%!\\t%0, %1, %2\";
969 "
970 [(set_attr "predicable" "yes")
971 (set_attr "length" "2")]
972 )
973
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"
980 "sub%!\\t%0, %1, %2"
981 [(set_attr "predicable" "yes")
982 (set_attr "length" "2")]
983 )
984
985 (define_peephole2
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" "")))]
989 "TARGET_THUMB2
990 && peep2_reg_dead_p (1, operands[1])
991 && satisfies_constraint_Pw (operands[2])"
992 [(parallel
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]));"
996 )
997
998 (define_peephole2
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" "")))]
1003 "TARGET_THUMB2
1004 && satisfies_constraint_Px (operands[2])"
1005 [(parallel
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]));"
1009 )
1010
1011 (define_insn "thumb2_addsi3_compare0"
1012 [(set (reg:CC_NOOV CC_REGNUM)
1013 (compare:CC_NOOV
1014 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1015 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1016 (const_int 0)))
1017 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1018 (plus:SI (match_dup 1) (match_dup 2)))]
1019 "TARGET_THUMB2"
1020 "*
1021 HOST_WIDE_INT val;
1022
1023 if (CONST_INT_P (operands[2]))
1024 val = INTVAL (operands[2]);
1025 else
1026 val = 0;
1027
1028 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1029 return \"subs\\t%0, %1, #%n2\";
1030 else
1031 return \"adds\\t%0, %1, %2\";
1032 "
1033 [(set_attr "conds" "set")
1034 (set_attr "length" "2,2,4")]
1035 )
1036
1037 (define_insn "*thumb2_addsi3_compare0_scratch"
1038 [(set (reg:CC_NOOV CC_REGNUM)
1039 (compare:CC_NOOV
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"))
1042 (const_int 0)))]
1043 "TARGET_THUMB2"
1044 "*
1045 HOST_WIDE_INT val;
1046
1047 if (CONST_INT_P (operands[1]))
1048 val = INTVAL (operands[1]);
1049 else
1050 val = 0;
1051
1052 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1053 return \"cmp\\t%0, #%n1\";
1054 else
1055 return \"cmn\\t%0, %1\";
1056 "
1057 [(set_attr "conds" "set")
1058 (set_attr "length" "2,2,4,4")
1059 (set_attr "type" "arlo_imm,*,arlo_imm,*")]
1060 )
1061
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")])
1072
1073 (define_insn "*thumb2_mulsi_short_compare0"
1074 [(set (reg:CC_NOOV CC_REGNUM)
1075 (compare:CC_NOOV
1076 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1077 (match_operand:SI 2 "register_operand" "l"))
1078 (const_int 0)))
1079 (set (match_operand:SI 0 "register_operand" "=l")
1080 (mult:SI (match_dup 1) (match_dup 2)))]
1081 "TARGET_THUMB2 && optimize_size"
1082 "muls\\t%0, %2, %0"
1083 [(set_attr "length" "2")
1084 (set_attr "type" "muls")])
1085
1086 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1087 [(set (reg:CC_NOOV CC_REGNUM)
1088 (compare:CC_NOOV
1089 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1090 (match_operand:SI 2 "register_operand" "l"))
1091 (const_int 0)))
1092 (clobber (match_scratch:SI 0 "=l"))]
1093 "TARGET_THUMB2 && optimize_size"
1094 "muls\\t%0, %2, %0"
1095 [(set_attr "length" "2")
1096 (set_attr "type" "muls")])
1097
1098 (define_insn "*thumb2_cbz"
1099 [(set (pc) (if_then_else
1100 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1101 (const_int 0))
1102 (label_ref (match_operand 1 "" ""))
1103 (pc)))
1104 (clobber (reg:CC CC_REGNUM))]
1105 "TARGET_THUMB2"
1106 "*
1107 if (get_attr_length (insn) == 2)
1108 return \"cbz\\t%0, %l1\";
1109 else
1110 return \"cmp\\t%0, #0\;beq\\t%l1\";
1111 "
1112 [(set (attr "length")
1113 (if_then_else
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")))
1117 (const_int 2)
1118 (const_int 8)))]
1119 )
1120
1121 (define_insn "*thumb2_cbnz"
1122 [(set (pc) (if_then_else
1123 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1124 (const_int 0))
1125 (label_ref (match_operand 1 "" ""))
1126 (pc)))
1127 (clobber (reg:CC CC_REGNUM))]
1128 "TARGET_THUMB2"
1129 "*
1130 if (get_attr_length (insn) == 2)
1131 return \"cbnz\\t%0, %l1\";
1132 else
1133 return \"cmp\\t%0, #0\;bne\\t%l1\";
1134 "
1135 [(set (attr "length")
1136 (if_then_else
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")))
1140 (const_int 2)
1141 (const_int 8)))]
1142 )
1143
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"
1149 "mvn%!\t%0, %1"
1150 [(set_attr "predicable" "yes")
1151 (set_attr "length" "2")]
1152 )
1153
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"
1159 "neg%!\t%0, %1"
1160 [(set_attr "predicable" "yes")
1161 (set_attr "length" "2")]
1162 )
1163
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")))]
1168 "TARGET_THUMB2"
1169 "orn%?\\t%0, %1, %2"
1170 [(set_attr "predicable" "yes")]
1171 )
1172
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")))]
1179 "TARGET_THUMB2"
1180 "orn%?\\t%0, %1, %2%S4"
1181 [(set_attr "predicable" "yes")
1182 (set_attr "shift" "2")
1183 (set_attr "type" "arlo_shift")]
1184 )
1185
1186 (define_peephole2
1187 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1188 (compare:CC_NOOV (zero_extract:SI
1189 (match_operand:SI 1 "low_register_operand" "")
1190 (const_int 1)
1191 (match_operand:SI 2 "const_int_operand" ""))
1192 (const_int 0)))
1193 (match_scratch:SI 3 "l")
1194 (set (pc)
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 "" "")))]
1199 "TARGET_THUMB2
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))
1203 (const_int 0)))
1204 (clobber (match_dup 3))])
1205 (set (pc)
1206 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1207 (match_dup 5) (match_dup 6)))]
1208 "
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);
1212 ")
1213
1214 (define_peephole2
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" "")
1219 (const_int 0))
1220 (const_int 0)))
1221 (match_scratch:SI 3 "l")
1222 (set (pc)
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 "" "")))]
1227 "TARGET_THUMB2
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))
1231 (const_int 0)))
1232 (clobber (match_dup 3))])
1233 (set (pc)
1234 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1235 (match_dup 5) (match_dup 6)))]
1236 "
1237 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1238 ")
1239
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
1249 "TARGET_32BIT"
1250 "
1251 {
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)
1259 {
1260 rtx s0;
1261 rtx bcomp;
1262 rtx loc_ref;
1263 rtx cc_reg;
1264 rtx insn;
1265 rtx cmp;
1266
1267 /* Only use this on innermost loops. */
1268 if (INTVAL (operands[3]) > 1)
1269 FAIL;
1270
1271 if (GET_MODE (operands[0]) != SImode)
1272 FAIL;
1273
1274 s0 = operands [0];
1275 if (TARGET_THUMB2)
1276 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1277 else
1278 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1279
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,
1286 loc_ref, pc_rtx)));
1287 DONE;
1288 }else
1289 FAIL;
1290 }")
1291