]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/thumb2.md
[ARM] Fix cmse_nonsecure_entry return insn size
[thirdparty/gcc.git] / gcc / config / arm / thumb2.md
1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2017 Free Software Foundation, Inc.
3 ;; Written by CodeSourcery, LLC.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11 ;;
12 ;; GCC is distributed in the hope that it will be useful, but
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ;; General Public License for more details.
16 ;;
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>. */
20
21 ;; Note: Thumb-2 is the variant of the Thumb architecture that adds
22 ;; 32-bit encodings of [almost all of] the Arm instruction set.
23 ;; Some old documents refer to the relatively minor interworking
24 ;; changes made in armv5t as "thumb2". These are considered part
25 ;; the 16-bit Thumb-1 instruction set.
26
27 ;; Thumb-2 only allows shift by constant on data processing instructions
28 (define_insn "*thumb_andsi_not_shiftsi_si"
29 [(set (match_operand:SI 0 "s_register_operand" "=r")
30 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
31 [(match_operand:SI 2 "s_register_operand" "r")
32 (match_operand:SI 3 "const_int_operand" "M")]))
33 (match_operand:SI 1 "s_register_operand" "r")))]
34 "TARGET_THUMB2"
35 "bic%?\\t%0, %1, %2%S4"
36 [(set_attr "predicable" "yes")
37 (set_attr "shift" "2")
38 (set_attr "type" "alu_shift_imm")]
39 )
40
41 ;; We use the '0' constraint for operand 1 because reload should
42 ;; be smart enough to generate an appropriate move for the r/r/r case.
43 (define_insn_and_split "*thumb2_smaxsi3"
44 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
45 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
46 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
47 (clobber (reg:CC CC_REGNUM))]
48 "TARGET_THUMB2"
49 "#"
50 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
51 "TARGET_THUMB2 && reload_completed"
52 [(set (reg:CC CC_REGNUM)
53 (compare:CC (match_dup 1) (match_dup 2)))
54 (cond_exec (lt:SI (reg:CC CC_REGNUM) (const_int 0))
55 (set (match_dup 0)
56 (match_dup 2)))]
57 ""
58 [(set_attr "conds" "clob")
59 (set_attr "enabled_for_short_it" "yes,yes,no")
60 (set_attr "length" "6,6,10")
61 (set_attr "type" "multiple")]
62 )
63
64 (define_insn_and_split "*thumb2_sminsi3"
65 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
66 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
67 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
68 (clobber (reg:CC CC_REGNUM))]
69 "TARGET_THUMB2"
70 "#"
71 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
72 "TARGET_THUMB2 && reload_completed"
73 [(set (reg:CC CC_REGNUM)
74 (compare:CC (match_dup 1) (match_dup 2)))
75 (cond_exec (ge:SI (reg:CC CC_REGNUM) (const_int 0))
76 (set (match_dup 0)
77 (match_dup 2)))]
78 ""
79 [(set_attr "conds" "clob")
80 (set_attr "enabled_for_short_it" "yes,yes,no")
81 (set_attr "length" "6,6,10")
82 (set_attr "type" "multiple")]
83 )
84
85 (define_insn_and_split "*thumb32_umaxsi3"
86 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
87 (umax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
88 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
89 (clobber (reg:CC CC_REGNUM))]
90 "TARGET_THUMB2"
91 "#"
92 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
93 "TARGET_THUMB2 && reload_completed"
94 [(set (reg:CC CC_REGNUM)
95 (compare:CC (match_dup 1) (match_dup 2)))
96 (cond_exec (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
97 (set (match_dup 0)
98 (match_dup 2)))]
99 ""
100 [(set_attr "conds" "clob")
101 (set_attr "length" "6,6,10")
102 (set_attr "enabled_for_short_it" "yes,yes,no")
103 (set_attr "type" "multiple")]
104 )
105
106 (define_insn_and_split "*thumb2_uminsi3"
107 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
108 (umin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
109 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
110 (clobber (reg:CC CC_REGNUM))]
111 "TARGET_THUMB2"
112 "#"
113 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
114 "TARGET_THUMB2 && reload_completed"
115 [(set (reg:CC CC_REGNUM)
116 (compare:CC (match_dup 1) (match_dup 2)))
117 (cond_exec (geu:SI (reg:CC CC_REGNUM) (const_int 0))
118 (set (match_dup 0)
119 (match_dup 2)))]
120 ""
121 [(set_attr "conds" "clob")
122 (set_attr "length" "6,6,10")
123 (set_attr "enabled_for_short_it" "yes,yes,no")
124 (set_attr "type" "multiple")]
125 )
126
127 (define_insn_and_split "*thumb2_abssi2"
128 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
129 (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0")))
130 (clobber (reg:CC CC_REGNUM))]
131 "TARGET_THUMB2"
132 "#"
133 ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
134 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
135 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
136 "&& reload_completed"
137 [(const_int 0)]
138 {
139 if (REGNO(operands[0]) == REGNO(operands[1]))
140 {
141 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
142
143 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
144 const0_rtx)));
145 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
146 (gen_rtx_LT (SImode,
147 cc_reg,
148 const0_rtx)),
149 (gen_rtx_SET (operands[0],
150 (gen_rtx_MINUS (SImode,
151 const0_rtx,
152 operands[1]))))));
153 }
154 else
155 {
156 emit_insn (gen_rtx_SET (operands[0],
157 gen_rtx_XOR (SImode,
158 gen_rtx_ASHIFTRT (SImode,
159 operands[1],
160 GEN_INT (31)),
161 operands[1])));
162 emit_insn (gen_rtx_SET (operands[0],
163 gen_rtx_MINUS (SImode,
164 operands[0],
165 gen_rtx_ASHIFTRT (SImode,
166 operands[1],
167 GEN_INT (31)))));
168 }
169 DONE;
170 }
171 [(set_attr "conds" "*,clob,clob")
172 (set_attr "shift" "1")
173 (set_attr "predicable" "yes,no,no")
174 (set_attr "enabled_for_short_it" "yes,yes,no")
175 (set_attr "ce_count" "2")
176 (set_attr "length" "8,6,10")
177 (set_attr "type" "multiple")]
178 )
179
180 (define_insn_and_split "*thumb2_neg_abssi2"
181 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
182 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0"))))
183 (clobber (reg:CC CC_REGNUM))]
184 "TARGET_THUMB2"
185 "#"
186 ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
187 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
188 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
189 "&& reload_completed"
190 [(const_int 0)]
191 {
192 if (REGNO(operands[0]) == REGNO(operands[1]))
193 {
194 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
195
196 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
197 const0_rtx)));
198 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
199 (gen_rtx_GT (SImode,
200 cc_reg,
201 const0_rtx)),
202 (gen_rtx_SET (operands[0],
203 (gen_rtx_MINUS (SImode,
204 const0_rtx,
205 operands[1]))))));
206 }
207 else
208 {
209 emit_insn (gen_rtx_SET (operands[0],
210 gen_rtx_XOR (SImode,
211 gen_rtx_ASHIFTRT (SImode,
212 operands[1],
213 GEN_INT (31)),
214 operands[1])));
215 emit_insn (gen_rtx_SET (operands[0],
216 gen_rtx_MINUS (SImode,
217 gen_rtx_ASHIFTRT (SImode,
218 operands[1],
219 GEN_INT (31)),
220 operands[0])));
221 }
222 DONE;
223 }
224 [(set_attr "conds" "*,clob,clob")
225 (set_attr "shift" "1")
226 (set_attr "predicable" "yes,no,no")
227 (set_attr "enabled_for_short_it" "yes,yes,no")
228 (set_attr "ce_count" "2")
229 (set_attr "length" "8,6,10")
230 (set_attr "type" "multiple")]
231 )
232
233 ;; Pop a single register as its size is preferred over a post-incremental load
234 (define_insn "*thumb2_pop_single"
235 [(set (match_operand:SI 0 "low_register_operand" "=r")
236 (mem:SI (post_inc:SI (reg:SI SP_REGNUM))))]
237 "TARGET_THUMB2 && (reload_in_progress || reload_completed)"
238 "pop\t{%0}"
239 [(set_attr "type" "load_4")
240 (set_attr "length" "2")
241 (set_attr "predicable" "yes")]
242 )
243
244 ;; We have two alternatives here for memory loads (and similarly for stores)
245 ;; to reflect the fact that the permissible constant pool ranges differ
246 ;; between ldr instructions taking low regs and ldr instructions taking high
247 ;; regs. The high register alternatives are not taken into account when
248 ;; choosing register preferences in order to reflect their expense.
249 (define_insn "*thumb2_movsi_insn"
250 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,l ,*hk,m,*m")
251 (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,*mi,l,*hk"))]
252 "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
253 && ( register_operand (operands[0], SImode)
254 || register_operand (operands[1], SImode))"
255 "@
256 mov%?\\t%0, %1
257 mov%?\\t%0, %1
258 mov%?\\t%0, %1
259 mvn%?\\t%0, #%B1
260 movw%?\\t%0, %1
261 ldr%?\\t%0, %1
262 ldr%?\\t%0, %1
263 str%?\\t%1, %0
264 str%?\\t%1, %0"
265 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mvn_imm,mov_imm,load_4,load_4,store_4,store_4")
266 (set_attr "length" "2,4,2,4,4,4,4,4,4")
267 (set_attr "predicable" "yes")
268 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no")
269 (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*")
270 (set_attr "neg_pool_range" "*,*,*,*,*,0,0,*,*")]
271 )
272
273 (define_insn "tls_load_dot_plus_four"
274 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
275 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
276 (const_int 4)
277 (match_operand 3 "" "")]
278 UNSPEC_PIC_BASE)))
279 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
280 "TARGET_THUMB2"
281 "*
282 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
283 INTVAL (operands[3]));
284 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
285 "
286 [(set_attr "length" "4,4,6,6")
287 (set_attr "type" "multiple")]
288 )
289
290 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
291 ;; of the messiness associated with the ARM patterns.
292 (define_insn "*thumb2_movhi_insn"
293 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,l,r,m,r")
294 (match_operand:HI 1 "general_operand" "rk,I,Py,n,r,m"))]
295 "TARGET_THUMB2
296 && (register_operand (operands[0], HImode)
297 || register_operand (operands[1], HImode))"
298 "@
299 mov%?\\t%0, %1\\t%@ movhi
300 mov%?\\t%0, %1\\t%@ movhi
301 mov%?\\t%0, %1\\t%@ movhi
302 movw%?\\t%0, %L1\\t%@ movhi
303 strh%?\\t%1, %0\\t%@ movhi
304 ldrh%?\\t%0, %1\\t%@ movhi"
305 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store_4,load_4")
306 (set_attr "predicable" "yes")
307 (set_attr "predicable_short_it" "yes,no,yes,no,no,no")
308 (set_attr "length" "2,4,2,4,4,4")
309 (set_attr "pool_range" "*,*,*,*,*,4094")
310 (set_attr "neg_pool_range" "*,*,*,*,*,250")]
311 )
312
313 (define_insn "*thumb2_storewb_pairsi"
314 [(set (match_operand:SI 0 "register_operand" "=&kr")
315 (plus:SI (match_operand:SI 1 "register_operand" "0")
316 (match_operand:SI 2 "const_int_operand" "n")))
317 (set (mem:SI (plus:SI (match_dup 0) (match_dup 2)))
318 (match_operand:SI 3 "register_operand" "r"))
319 (set (mem:SI (plus:SI (match_dup 0)
320 (match_operand:SI 5 "const_int_operand" "n")))
321 (match_operand:SI 4 "register_operand" "r"))]
322 "TARGET_THUMB2
323 && INTVAL (operands[5]) == INTVAL (operands[2]) + 4"
324 "strd\\t%3, %4, [%0, %2]!"
325 [(set_attr "type" "store_8")]
326 )
327
328 (define_insn "*thumb2_cmpsi_neg_shiftsi"
329 [(set (reg:CC CC_REGNUM)
330 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
331 (neg:SI (match_operator:SI 3 "shift_operator"
332 [(match_operand:SI 1 "s_register_operand" "r")
333 (match_operand:SI 2 "const_int_operand" "M")]))))]
334 "TARGET_THUMB2"
335 "cmn%?\\t%0, %1%S3"
336 [(set_attr "conds" "set")
337 (set_attr "shift" "1")
338 (set_attr "type" "alus_shift_imm")]
339 )
340
341 (define_insn_and_split "*thumb2_mov_scc"
342 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
343 (match_operator:SI 1 "arm_comparison_operator_mode"
344 [(match_operand 2 "cc_register" "") (const_int 0)]))]
345 "TARGET_THUMB2"
346 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
347 "TARGET_THUMB2"
348 [(set (match_dup 0)
349 (if_then_else:SI (match_dup 1)
350 (const_int 1)
351 (const_int 0)))]
352 ""
353 [(set_attr "conds" "use")
354 (set_attr "enabled_for_short_it" "yes,no")
355 (set_attr "length" "8,10")
356 (set_attr "type" "multiple")]
357 )
358
359 (define_insn_and_split "*thumb2_mov_negscc"
360 [(set (match_operand:SI 0 "s_register_operand" "=r")
361 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
362 [(match_operand 2 "cc_register" "") (const_int 0)])))]
363 "TARGET_THUMB2 && !arm_restrict_it"
364 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
365 "TARGET_THUMB2"
366 [(set (match_dup 0)
367 (if_then_else:SI (match_dup 1)
368 (match_dup 3)
369 (const_int 0)))]
370 {
371 operands[3] = GEN_INT (~0);
372 }
373 [(set_attr "conds" "use")
374 (set_attr "length" "10")
375 (set_attr "type" "multiple")]
376 )
377
378 (define_insn_and_split "*thumb2_mov_negscc_strict_it"
379 [(set (match_operand:SI 0 "low_register_operand" "=l")
380 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
381 [(match_operand 2 "cc_register" "") (const_int 0)])))]
382 "TARGET_THUMB2 && arm_restrict_it"
383 "#" ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\"
384 "&& reload_completed"
385 [(set (match_dup 0)
386 (match_dup 3))
387 (cond_exec (match_dup 4)
388 (set (match_dup 0)
389 (const_int 0)))]
390 {
391 operands[3] = GEN_INT (~0);
392 machine_mode mode = GET_MODE (operands[2]);
393 enum rtx_code rc = GET_CODE (operands[1]);
394
395 if (mode == CCFPmode || mode == CCFPEmode)
396 rc = reverse_condition_maybe_unordered (rc);
397 else
398 rc = reverse_condition (rc);
399 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
400
401 }
402 [(set_attr "conds" "use")
403 (set_attr "length" "8")
404 (set_attr "type" "multiple")]
405 )
406
407 (define_insn_and_split "*thumb2_mov_notscc"
408 [(set (match_operand:SI 0 "s_register_operand" "=r")
409 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
410 [(match_operand 2 "cc_register" "") (const_int 0)])))]
411 "TARGET_THUMB2 && !arm_restrict_it"
412 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
413 "TARGET_THUMB2"
414 [(set (match_dup 0)
415 (if_then_else:SI (match_dup 1)
416 (match_dup 3)
417 (match_dup 4)))]
418 {
419 operands[3] = GEN_INT (~1);
420 operands[4] = GEN_INT (~0);
421 }
422 [(set_attr "conds" "use")
423 (set_attr "length" "10")
424 (set_attr "type" "multiple")]
425 )
426
427 (define_insn_and_split "*thumb2_mov_notscc_strict_it"
428 [(set (match_operand:SI 0 "low_register_operand" "=l")
429 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
430 [(match_operand 2 "cc_register" "") (const_int 0)])))]
431 "TARGET_THUMB2 && arm_restrict_it"
432 "#" ; "mvn %0, #0 ; it%d1 ; lsl%d1 %0, %0, #1"
433 "&& reload_completed"
434 [(set (match_dup 0)
435 (match_dup 3))
436 (cond_exec (match_dup 4)
437 (set (match_dup 0)
438 (ashift:SI (match_dup 0)
439 (const_int 1))))]
440 {
441 operands[3] = GEN_INT (~0);
442 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
443 VOIDmode, operands[2], const0_rtx);
444 }
445 [(set_attr "conds" "use")
446 (set_attr "length" "8")
447 (set_attr "type" "multiple")]
448 )
449
450 (define_insn_and_split "*thumb2_movsicc_insn"
451 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r")
452 (if_then_else:SI
453 (match_operator 3 "arm_comparison_operator"
454 [(match_operand 4 "cc_register" "") (const_int 0)])
455 (match_operand:SI 1 "arm_not_operand" "0 ,lPy,0 ,0,rI,K,I ,r,rI,K ,K,r")
456 (match_operand:SI 2 "arm_not_operand" "lPy,0 ,rI,K,0 ,0,rI,I,K ,rI,K,r")))]
457 "TARGET_THUMB2"
458 "@
459 it\\t%D3\;mov%D3\\t%0, %2
460 it\\t%d3\;mov%d3\\t%0, %1
461 it\\t%D3\;mov%D3\\t%0, %2
462 it\\t%D3\;mvn%D3\\t%0, #%B2
463 it\\t%d3\;mov%d3\\t%0, %1
464 it\\t%d3\;mvn%d3\\t%0, #%B1
465 #
466 #
467 #
468 #
469 #
470 #"
471 ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
472 ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
473 ; alt 8: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
474 ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
475 ; alt 10: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
476 ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
477 "&& reload_completed"
478 [(const_int 0)]
479 {
480 enum rtx_code rev_code;
481 machine_mode mode;
482 rtx rev_cond;
483
484 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
485 operands[3],
486 gen_rtx_SET (operands[0], operands[1])));
487 rev_code = GET_CODE (operands[3]);
488 mode = GET_MODE (operands[4]);
489 if (mode == CCFPmode || mode == CCFPEmode)
490 rev_code = reverse_condition_maybe_unordered (rev_code);
491 else
492 rev_code = reverse_condition (rev_code);
493
494 rev_cond = gen_rtx_fmt_ee (rev_code,
495 VOIDmode,
496 gen_rtx_REG (mode, CC_REGNUM),
497 const0_rtx);
498 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
499 rev_cond,
500 gen_rtx_SET (operands[0], operands[2])));
501 DONE;
502 }
503 [(set_attr "length" "4,4,6,6,6,6,10,8,10,10,10,6")
504 (set_attr "enabled_for_short_it" "yes,yes,no,no,no,no,no,no,no,no,no,yes")
505 (set_attr "conds" "use")
506 (set_attr_alternative "type"
507 [(if_then_else (match_operand 2 "const_int_operand" "")
508 (const_string "mov_imm")
509 (const_string "mov_reg"))
510 (if_then_else (match_operand 1 "const_int_operand" "")
511 (const_string "mov_imm")
512 (const_string "mov_reg"))
513 (if_then_else (match_operand 2 "const_int_operand" "")
514 (const_string "mov_imm")
515 (const_string "mov_reg"))
516 (const_string "mvn_imm")
517 (if_then_else (match_operand 1 "const_int_operand" "")
518 (const_string "mov_imm")
519 (const_string "mov_reg"))
520 (const_string "mvn_imm")
521 (const_string "multiple")
522 (const_string "multiple")
523 (const_string "multiple")
524 (const_string "multiple")
525 (const_string "multiple")
526 (const_string "multiple")])]
527 )
528
529 (define_insn "*thumb2_movsfcc_soft_insn"
530 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
531 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
532 [(match_operand 4 "cc_register" "") (const_int 0)])
533 (match_operand:SF 1 "s_register_operand" "0,r")
534 (match_operand:SF 2 "s_register_operand" "r,0")))]
535 "TARGET_THUMB2 && TARGET_SOFT_FLOAT"
536 "@
537 it\\t%D3\;mov%D3\\t%0, %2
538 it\\t%d3\;mov%d3\\t%0, %1"
539 [(set_attr "length" "6,6")
540 (set_attr "conds" "use")
541 (set_attr "type" "multiple")]
542 )
543
544 (define_insn "*call_reg_thumb2"
545 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
546 (match_operand 1 "" ""))
547 (use (match_operand 2 "" ""))
548 (clobber (reg:SI LR_REGNUM))]
549 "TARGET_THUMB2"
550 "blx%?\\t%0"
551 [(set_attr "type" "call")]
552 )
553
554 (define_insn "*nonsecure_call_reg_thumb2"
555 [(call (unspec:SI [(mem:SI (match_operand:SI 0 "s_register_operand" "r"))]
556 UNSPEC_NONSECURE_MEM)
557 (match_operand 1 "" ""))
558 (use (match_operand 2 "" ""))
559 (clobber (reg:SI LR_REGNUM))
560 (clobber (match_dup 0))]
561 "TARGET_THUMB2 && use_cmse"
562 "bl\\t__gnu_cmse_nonsecure_call"
563 [(set_attr "length" "4")
564 (set_attr "type" "call")]
565 )
566
567 (define_insn "*call_value_reg_thumb2"
568 [(set (match_operand 0 "" "")
569 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
570 (match_operand 2 "" "")))
571 (use (match_operand 3 "" ""))
572 (clobber (reg:SI LR_REGNUM))]
573 "TARGET_THUMB2"
574 "blx\\t%1"
575 [(set_attr "type" "call")]
576 )
577
578 (define_insn "*nonsecure_call_value_reg_thumb2"
579 [(set (match_operand 0 "" "")
580 (call
581 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
582 UNSPEC_NONSECURE_MEM)
583 (match_operand 2 "" "")))
584 (use (match_operand 3 "" ""))
585 (clobber (reg:SI LR_REGNUM))
586 (clobber (match_dup 1))]
587 "TARGET_THUMB2 && use_cmse"
588 "bl\t__gnu_cmse_nonsecure_call"
589 [(set_attr "length" "4")
590 (set_attr "type" "call")]
591 )
592
593 (define_insn "*thumb2_indirect_jump"
594 [(set (pc)
595 (match_operand:SI 0 "register_operand" "l*r"))]
596 "TARGET_THUMB2"
597 "bx\\t%0"
598 [(set_attr "conds" "clob")
599 (set_attr "type" "branch")]
600 )
601 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
602 ;; addresses will have the thumb bit set correctly.
603
604
605 (define_insn_and_split "*thumb2_and_scc"
606 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
607 (and:SI (match_operator:SI 1 "arm_comparison_operator"
608 [(match_operand 2 "cc_register" "") (const_int 0)])
609 (match_operand:SI 3 "s_register_operand" "r")))]
610 "TARGET_THUMB2"
611 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
612 "&& reload_completed"
613 [(set (match_dup 0)
614 (and:SI (match_dup 3) (const_int 1)))
615 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
616 {
617 machine_mode mode = GET_MODE (operands[2]);
618 enum rtx_code rc = GET_CODE (operands[1]);
619
620 if (mode == CCFPmode || mode == CCFPEmode)
621 rc = reverse_condition_maybe_unordered (rc);
622 else
623 rc = reverse_condition (rc);
624 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
625 }
626 [(set_attr "conds" "use")
627 (set_attr "type" "multiple")
628 (set (attr "length") (if_then_else (match_test "arm_restrict_it")
629 (const_int 8)
630 (const_int 10)))]
631 )
632
633 (define_insn_and_split "*thumb2_ior_scc"
634 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
635 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
636 [(match_operand 2 "cc_register" "") (const_int 0)])
637 (match_operand:SI 3 "s_register_operand" "0,?r")))]
638 "TARGET_THUMB2 && !arm_restrict_it"
639 "@
640 it\\t%d1\;orr%d1\\t%0, %3, #1
641 #"
642 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
643 "&& reload_completed
644 && REGNO (operands [0]) != REGNO (operands[3])"
645 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
646 (cond_exec (match_dup 4) (set (match_dup 0)
647 (ior:SI (match_dup 3) (const_int 1))))]
648 {
649 machine_mode mode = GET_MODE (operands[2]);
650 enum rtx_code rc = GET_CODE (operands[1]);
651
652 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
653 if (mode == CCFPmode || mode == CCFPEmode)
654 rc = reverse_condition_maybe_unordered (rc);
655 else
656 rc = reverse_condition (rc);
657 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
658 }
659 [(set_attr "conds" "use")
660 (set_attr "length" "6,10")
661 (set_attr "type" "multiple")]
662 )
663
664 (define_insn_and_split "*thumb2_ior_scc_strict_it"
665 [(set (match_operand:SI 0 "s_register_operand" "=&r")
666 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
667 [(match_operand 3 "cc_register" "") (const_int 0)])
668 (match_operand:SI 1 "s_register_operand" "r")))]
669 "TARGET_THUMB2 && arm_restrict_it"
670 "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
671 "&& reload_completed"
672 [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
673 (cond_exec (match_dup 4)
674 (set (match_dup 0) (match_dup 1)))]
675 {
676 machine_mode mode = GET_MODE (operands[3]);
677 rtx_code rc = GET_CODE (operands[2]);
678
679 if (mode == CCFPmode || mode == CCFPEmode)
680 rc = reverse_condition_maybe_unordered (rc);
681 else
682 rc = reverse_condition (rc);
683 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
684 }
685 [(set_attr "conds" "use")
686 (set_attr "length" "8")
687 (set_attr "type" "multiple")]
688 )
689
690 (define_insn "*thumb2_cond_move"
691 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
692 (if_then_else:SI (match_operator 3 "equality_operator"
693 [(match_operator 4 "arm_comparison_operator"
694 [(match_operand 5 "cc_register" "") (const_int 0)])
695 (const_int 0)])
696 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
697 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
698 "TARGET_THUMB2"
699 "*
700 if (GET_CODE (operands[3]) == NE)
701 {
702 if (which_alternative != 1)
703 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
704 if (which_alternative != 0)
705 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
706 return \"\";
707 }
708 switch (which_alternative)
709 {
710 case 0:
711 output_asm_insn (\"it\\t%d4\", operands);
712 break;
713 case 1:
714 output_asm_insn (\"it\\t%D4\", operands);
715 break;
716 case 2:
717 if (arm_restrict_it)
718 output_asm_insn (\"it\\t%D4\", operands);
719 else
720 output_asm_insn (\"ite\\t%D4\", operands);
721 break;
722 default:
723 abort();
724 }
725 if (which_alternative != 0)
726 {
727 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
728 if (arm_restrict_it && which_alternative == 2)
729 output_asm_insn (\"it\\t%d4\", operands);
730 }
731 if (which_alternative != 1)
732 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
733 return \"\";
734 "
735 [(set_attr "conds" "use")
736 (set_attr "length" "6,6,10")
737 (set_attr "type" "multiple")]
738 )
739
740 (define_insn "*thumb2_cond_arith"
741 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
742 (match_operator:SI 5 "shiftable_operator"
743 [(match_operator:SI 4 "arm_comparison_operator"
744 [(match_operand:SI 2 "s_register_operand" "r,r")
745 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
746 (match_operand:SI 1 "s_register_operand" "0,?r")]))
747 (clobber (reg:CC CC_REGNUM))]
748 "TARGET_THUMB2 && !arm_restrict_it"
749 "*
750 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
751 return \"%i5\\t%0, %1, %2, lsr #31\";
752
753 output_asm_insn (\"cmp\\t%2, %3\", operands);
754 if (GET_CODE (operands[5]) == AND)
755 {
756 output_asm_insn (\"ite\\t%D4\", operands);
757 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
758 }
759 else if (GET_CODE (operands[5]) == MINUS)
760 {
761 output_asm_insn (\"ite\\t%D4\", operands);
762 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
763 }
764 else if (which_alternative != 0)
765 {
766 output_asm_insn (\"ite\\t%D4\", operands);
767 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
768 }
769 else
770 output_asm_insn (\"it\\t%d4\", operands);
771 return \"%i5%d4\\t%0, %1, #1\";
772 "
773 [(set_attr "conds" "clob")
774 (set_attr "length" "14")
775 (set_attr "type" "multiple")]
776 )
777
778 (define_insn_and_split "*thumb2_cond_arith_strict_it"
779 [(set (match_operand:SI 0 "s_register_operand" "=l")
780 (match_operator:SI 5 "shiftable_operator_strict_it"
781 [(match_operator:SI 4 "arm_comparison_operator"
782 [(match_operand:SI 2 "s_register_operand" "r")
783 (match_operand:SI 3 "arm_rhs_operand" "rI")])
784 (match_operand:SI 1 "s_register_operand" "0")]))
785 (clobber (reg:CC CC_REGNUM))]
786 "TARGET_THUMB2 && arm_restrict_it"
787 "#"
788 "&& reload_completed"
789 [(const_int 0)]
790 {
791 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
792 {
793 /* %i5 %0, %1, %2, lsr #31 */
794 rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
795 rtx op = NULL_RTX;
796
797 switch (GET_CODE (operands[5]))
798 {
799 case AND:
800 op = gen_rtx_AND (SImode, shifted_op, operands[1]);
801 break;
802 case PLUS:
803 op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
804 break;
805 default: gcc_unreachable ();
806 }
807 emit_insn (gen_rtx_SET (operands[0], op));
808 DONE;
809 }
810
811 /* "cmp %2, %3" */
812 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
813 gen_rtx_COMPARE (CCmode, operands[2],
814 operands[3])));
815
816 if (GET_CODE (operands[5]) == AND)
817 {
818 /* %i5 %0, %1, #1
819 it%D4
820 mov%D4 %0, #0 */
821 enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
822 emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
823 GEN_INT (1))));
824 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
825 gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
826 gen_rtx_SET (operands[0], const0_rtx)));
827 DONE;
828 }
829 else
830 {
831 /* it\\t%d4
832 %i5%d4\\t%0, %1, #1 */
833 emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
834 VOIDmode,
835 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
836 gen_rtx_SET (operands[0],
837 gen_rtx_PLUS (SImode,
838 operands[1],
839 GEN_INT (1)))));
840 DONE;
841 }
842 FAIL;
843 }
844 [(set_attr "conds" "clob")
845 (set_attr "length" "12")
846 (set_attr "type" "multiple")]
847 )
848
849 (define_insn "*thumb2_cond_sub"
850 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
851 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
852 (match_operator:SI 4 "arm_comparison_operator"
853 [(match_operand:SI 2 "s_register_operand" "r,r")
854 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
855 (clobber (reg:CC CC_REGNUM))]
856 "TARGET_THUMB2"
857 "*
858 output_asm_insn (\"cmp\\t%2, %3\", operands);
859 if (which_alternative != 0)
860 {
861 if (arm_restrict_it)
862 {
863 output_asm_insn (\"mov\\t%0, %1\", operands);
864 output_asm_insn (\"it\\t%d4\", operands);
865 }
866 else
867 {
868 output_asm_insn (\"ite\\t%D4\", operands);
869 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
870 }
871 }
872 else
873 output_asm_insn (\"it\\t%d4\", operands);
874 return \"sub%d4\\t%0, %1, #1\";
875 "
876 [(set_attr "conds" "clob")
877 (set_attr "length" "10,14")
878 (set_attr "type" "multiple")]
879 )
880
881 (define_insn_and_split "*thumb2_negscc"
882 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
883 (neg:SI (match_operator 3 "arm_comparison_operator"
884 [(match_operand:SI 1 "s_register_operand" "r")
885 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
886 (clobber (reg:CC CC_REGNUM))]
887 "TARGET_THUMB2"
888 "#"
889 "&& reload_completed"
890 [(const_int 0)]
891 {
892 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
893
894 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
895 {
896 /* Emit asr\\t%0, %1, #31 */
897 emit_insn (gen_rtx_SET (operands[0],
898 gen_rtx_ASHIFTRT (SImode,
899 operands[1],
900 GEN_INT (31))));
901 DONE;
902 }
903 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
904 {
905 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
906 if (CONST_INT_P (operands[2]))
907 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
908 GEN_INT (- INTVAL (operands[2]))));
909 else
910 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
911
912 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
913 gen_rtx_NE (SImode,
914 cc_reg,
915 const0_rtx),
916 gen_rtx_SET (operands[0],
917 GEN_INT (~0))));
918 DONE;
919 }
920 else
921 {
922 /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
923 enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
924 machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
925 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
926
927 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
928 operands[2])));
929
930 emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
931
932 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
933 gen_rtx_fmt_ee (rc,
934 VOIDmode,
935 tmp1,
936 const0_rtx),
937 gen_rtx_SET (operands[0], const0_rtx)));
938 DONE;
939 }
940 FAIL;
941 }
942 [(set_attr "conds" "clob")
943 (set_attr "length" "14")
944 (set_attr "type" "multiple")]
945 )
946
947 (define_insn "*thumb2_movcond"
948 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
949 (if_then_else:SI
950 (match_operator 5 "arm_comparison_operator"
951 [(match_operand:SI 3 "s_register_operand" "r,r,r")
952 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
953 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
954 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
955 (clobber (reg:CC CC_REGNUM))]
956 "TARGET_THUMB2"
957 "*
958 if (GET_CODE (operands[5]) == LT
959 && (operands[4] == const0_rtx))
960 {
961 if (which_alternative != 1 && REG_P (operands[1]))
962 {
963 if (operands[2] == const0_rtx)
964 return \"and\\t%0, %1, %3, asr #31\";
965 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
966 }
967 else if (which_alternative != 0 && REG_P (operands[2]))
968 {
969 if (operands[1] == const0_rtx)
970 return \"bic\\t%0, %2, %3, asr #31\";
971 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
972 }
973 /* The only case that falls through to here is when both ops 1 & 2
974 are constants. */
975 }
976
977 if (GET_CODE (operands[5]) == GE
978 && (operands[4] == const0_rtx))
979 {
980 if (which_alternative != 1 && REG_P (operands[1]))
981 {
982 if (operands[2] == const0_rtx)
983 return \"bic\\t%0, %1, %3, asr #31\";
984 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
985 }
986 else if (which_alternative != 0 && REG_P (operands[2]))
987 {
988 if (operands[1] == const0_rtx)
989 return \"and\\t%0, %2, %3, asr #31\";
990 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
991 }
992 /* The only case that falls through to here is when both ops 1 & 2
993 are constants. */
994 }
995 if (CONST_INT_P (operands[4])
996 && !const_ok_for_arm (INTVAL (operands[4])))
997 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
998 else
999 output_asm_insn (\"cmp\\t%3, %4\", operands);
1000 switch (which_alternative)
1001 {
1002 case 0:
1003 output_asm_insn (\"it\\t%D5\", operands);
1004 break;
1005 case 1:
1006 output_asm_insn (\"it\\t%d5\", operands);
1007 break;
1008 case 2:
1009 if (arm_restrict_it)
1010 {
1011 output_asm_insn (\"mov\\t%0, %1\", operands);
1012 output_asm_insn (\"it\\t%D5\", operands);
1013 }
1014 else
1015 output_asm_insn (\"ite\\t%d5\", operands);
1016 break;
1017 default:
1018 abort();
1019 }
1020 if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1021 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1022 if (which_alternative != 1)
1023 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1024 return \"\";
1025 "
1026 [(set_attr "conds" "clob")
1027 (set_attr "length" "10,10,14")
1028 (set_attr "type" "multiple")]
1029 )
1030
1031 ;; Zero and sign extension instructions.
1032
1033 ;; All supported Thumb2 implementations are armv6, so only that case is
1034 ;; provided.
1035 (define_insn "*thumb2_extendqisi_v6"
1036 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1037 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1038 "TARGET_THUMB2 && arm_arch6"
1039 "@
1040 sxtb%?\\t%0, %1
1041 ldrsb%?\\t%0, %1"
1042 [(set_attr "type" "extend,load_byte")
1043 (set_attr "predicable" "yes")
1044 (set_attr "pool_range" "*,4094")
1045 (set_attr "neg_pool_range" "*,250")]
1046 )
1047
1048 (define_insn "*thumb2_zero_extendhisi2_v6"
1049 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1050 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1051 "TARGET_THUMB2 && arm_arch6"
1052 "@
1053 uxth%?\\t%0, %1
1054 ldrh%?\\t%0, %1"
1055 [(set_attr "type" "extend,load_byte")
1056 (set_attr "predicable" "yes")
1057 (set_attr "pool_range" "*,4094")
1058 (set_attr "neg_pool_range" "*,250")]
1059 )
1060
1061 (define_insn "thumb2_zero_extendqisi2_v6"
1062 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1063 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1064 "TARGET_THUMB2 && arm_arch6"
1065 "@
1066 uxtb%?\\t%0, %1
1067 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1068 [(set_attr "type" "extend,load_byte")
1069 (set_attr "predicable" "yes")
1070 (set_attr "pool_range" "*,4094")
1071 (set_attr "neg_pool_range" "*,250")]
1072 )
1073
1074 (define_insn "thumb2_casesi_internal"
1075 [(parallel [(set (pc)
1076 (if_then_else
1077 (leu (match_operand:SI 0 "s_register_operand" "r")
1078 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1079 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1080 (label_ref (match_operand 2 "" ""))))
1081 (label_ref (match_operand 3 "" ""))))
1082 (clobber (reg:CC CC_REGNUM))
1083 (clobber (match_scratch:SI 4 "=&r"))
1084 (use (label_ref (match_dup 2)))])]
1085 "TARGET_THUMB2 && !flag_pic"
1086 "* return thumb2_output_casesi(operands);"
1087 [(set_attr "conds" "clob")
1088 (set_attr "length" "16")
1089 (set_attr "type" "multiple")]
1090 )
1091
1092 (define_insn "thumb2_casesi_internal_pic"
1093 [(parallel [(set (pc)
1094 (if_then_else
1095 (leu (match_operand:SI 0 "s_register_operand" "r")
1096 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1097 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1098 (label_ref (match_operand 2 "" ""))))
1099 (label_ref (match_operand 3 "" ""))))
1100 (clobber (reg:CC CC_REGNUM))
1101 (clobber (match_scratch:SI 4 "=&r"))
1102 (clobber (match_scratch:SI 5 "=r"))
1103 (use (label_ref (match_dup 2)))])]
1104 "TARGET_THUMB2 && flag_pic"
1105 "* return thumb2_output_casesi(operands);"
1106 [(set_attr "conds" "clob")
1107 (set_attr "length" "20")
1108 (set_attr "type" "multiple")]
1109 )
1110
1111 (define_insn "*thumb2_return"
1112 [(simple_return)]
1113 "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1114 "* return output_return_instruction (const_true_rtx, true, false, true);"
1115 [(set_attr "type" "branch")
1116 (set_attr "length" "4")]
1117 )
1118
1119 (define_insn "*thumb2_cmse_entry_return"
1120 [(simple_return)]
1121 "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1122 "* return output_return_instruction (const_true_rtx, true, false, true);"
1123 [(set_attr "type" "branch")
1124 ; This is a return from a cmse_nonsecure_entry function so code will be
1125 ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1126 ; we adapt the length accordingly.
1127 (set (attr "length")
1128 (if_then_else (match_test "TARGET_HARD_FLOAT")
1129 (const_int 34)
1130 (const_int 8)))
1131 ; We do not support predicate execution of returns from cmse_nonsecure_entry
1132 ; functions because we need to clear the APSR. Since predicable has to be
1133 ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1134 ; functions.
1135 (set_attr "predicable" "no")]
1136 )
1137
1138 (define_insn_and_split "thumb2_eh_return"
1139 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1140 VUNSPEC_EH_RETURN)
1141 (clobber (match_scratch:SI 1 "=&r"))]
1142 "TARGET_THUMB2"
1143 "#"
1144 "&& reload_completed"
1145 [(const_int 0)]
1146 "
1147 {
1148 thumb_set_return_address (operands[0], operands[1]);
1149 DONE;
1150 }"
1151 )
1152
1153 (define_insn "*thumb2_alusi3_short"
1154 [(set (match_operand:SI 0 "s_register_operand" "=l")
1155 (match_operator:SI 3 "thumb_16bit_operator"
1156 [(match_operand:SI 1 "s_register_operand" "0")
1157 (match_operand:SI 2 "s_register_operand" "l")]))
1158 (clobber (reg:CC CC_REGNUM))]
1159 "TARGET_THUMB2 && reload_completed
1160 && GET_CODE(operands[3]) != PLUS
1161 && GET_CODE(operands[3]) != MINUS"
1162 "%I3%!\\t%0, %1, %2"
1163 [(set_attr "predicable" "yes")
1164 (set_attr "length" "2")
1165 (set_attr "type" "alu_sreg")]
1166 )
1167
1168 (define_insn "*thumb2_shiftsi3_short"
1169 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1170 (match_operator:SI 3 "shift_operator"
1171 [(match_operand:SI 1 "low_register_operand" "0,l")
1172 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1173 (clobber (reg:CC CC_REGNUM))]
1174 "TARGET_THUMB2 && reload_completed
1175 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1176 || REG_P (operands[2]))"
1177 "* return arm_output_shift(operands, 2);"
1178 [(set_attr "predicable" "yes")
1179 (set_attr "shift" "1")
1180 (set_attr "length" "2")
1181 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1182 (const_string "alu_shift_imm")
1183 (const_string "alu_shift_reg")))]
1184 )
1185
1186 (define_insn "*thumb2_mov<mode>_shortim"
1187 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1188 (match_operand:QHSI 1 "const_int_operand" "I"))
1189 (clobber (reg:CC CC_REGNUM))]
1190 "TARGET_THUMB2 && reload_completed"
1191 "mov%!\t%0, %1"
1192 [(set_attr "predicable" "yes")
1193 (set_attr "length" "2")
1194 (set_attr "type" "mov_imm")]
1195 )
1196
1197 (define_insn "*thumb2_addsi_short"
1198 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1199 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1200 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1201 (clobber (reg:CC CC_REGNUM))]
1202 "TARGET_THUMB2 && reload_completed"
1203 "*
1204 HOST_WIDE_INT val;
1205
1206 if (CONST_INT_P (operands[2]))
1207 val = INTVAL(operands[2]);
1208 else
1209 val = 0;
1210
1211 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
1212 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1213 return \"sub%!\\t%0, %1, #%n2\";
1214 else
1215 return \"add%!\\t%0, %1, %2\";
1216 "
1217 [(set_attr "predicable" "yes")
1218 (set_attr "length" "2")
1219 (set_attr_alternative "type"
1220 [(if_then_else (match_operand 2 "const_int_operand" "")
1221 (const_string "alu_imm")
1222 (const_string "alu_sreg"))
1223 (const_string "alu_imm")])]
1224 )
1225
1226 (define_insn "*thumb2_subsi_short"
1227 [(set (match_operand:SI 0 "low_register_operand" "=l")
1228 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1229 (match_operand:SI 2 "low_register_operand" "l")))
1230 (clobber (reg:CC CC_REGNUM))]
1231 "TARGET_THUMB2 && reload_completed"
1232 "sub%!\\t%0, %1, %2"
1233 [(set_attr "predicable" "yes")
1234 (set_attr "length" "2")
1235 (set_attr "type" "alu_sreg")]
1236 )
1237
1238 (define_peephole2
1239 [(set (match_operand:CC 0 "cc_register" "")
1240 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1241 (match_operand:SI 2 "const_int_operand" "")))]
1242 "TARGET_THUMB2
1243 && peep2_reg_dead_p (1, operands[1])
1244 && satisfies_constraint_Pw (operands[2])"
1245 [(parallel
1246 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1247 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1248 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1249 )
1250
1251 (define_peephole2
1252 [(match_scratch:SI 3 "l")
1253 (set (match_operand:CC 0 "cc_register" "")
1254 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1255 (match_operand:SI 2 "const_int_operand" "")))]
1256 "TARGET_THUMB2
1257 && satisfies_constraint_Px (operands[2])"
1258 [(parallel
1259 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1260 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1261 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1262 )
1263
1264 (define_insn "thumb2_addsi3_compare0"
1265 [(set (reg:CC_NOOV CC_REGNUM)
1266 (compare:CC_NOOV
1267 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1268 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1269 (const_int 0)))
1270 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1271 (plus:SI (match_dup 1) (match_dup 2)))]
1272 "TARGET_THUMB2"
1273 "*
1274 HOST_WIDE_INT val;
1275
1276 if (CONST_INT_P (operands[2]))
1277 val = INTVAL (operands[2]);
1278 else
1279 val = 0;
1280
1281 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1282 return \"subs\\t%0, %1, #%n2\";
1283 else
1284 return \"adds\\t%0, %1, %2\";
1285 "
1286 [(set_attr "conds" "set")
1287 (set_attr "length" "2,2,4")
1288 (set_attr_alternative "type"
1289 [(if_then_else (match_operand 2 "const_int_operand" "")
1290 (const_string "alus_imm")
1291 (const_string "alus_sreg"))
1292 (const_string "alus_imm")
1293 (if_then_else (match_operand 2 "const_int_operand" "")
1294 (const_string "alus_imm")
1295 (const_string "alus_sreg"))])]
1296 )
1297
1298 (define_insn "*thumb2_addsi3_compare0_scratch"
1299 [(set (reg:CC_NOOV CC_REGNUM)
1300 (compare:CC_NOOV
1301 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r")
1302 (match_operand:SI 1 "arm_add_operand" "lPv,rIL"))
1303 (const_int 0)))]
1304 "TARGET_THUMB2"
1305 "*
1306 HOST_WIDE_INT val;
1307
1308 if (CONST_INT_P (operands[1]))
1309 val = INTVAL (operands[1]);
1310 else
1311 val = 0;
1312
1313 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1314 return \"cmp\\t%0, #%n1\";
1315 else
1316 return \"cmn\\t%0, %1\";
1317 "
1318 [(set_attr "conds" "set")
1319 (set_attr "length" "2,4")
1320 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1321 (const_string "alus_imm")
1322 (const_string "alus_sreg")))]
1323 )
1324
1325 (define_insn "*thumb2_mulsi_short"
1326 [(set (match_operand:SI 0 "low_register_operand" "=l")
1327 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1328 (match_operand:SI 2 "low_register_operand" "l")))
1329 (clobber (reg:CC CC_REGNUM))]
1330 "TARGET_THUMB2 && optimize_size && reload_completed"
1331 "mul%!\\t%0, %2, %0"
1332 [(set_attr "predicable" "yes")
1333 (set_attr "length" "2")
1334 (set_attr "type" "muls")])
1335
1336 (define_insn "*thumb2_mulsi_short_compare0"
1337 [(set (reg:CC_NOOV CC_REGNUM)
1338 (compare:CC_NOOV
1339 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1340 (match_operand:SI 2 "register_operand" "l"))
1341 (const_int 0)))
1342 (set (match_operand:SI 0 "register_operand" "=l")
1343 (mult:SI (match_dup 1) (match_dup 2)))]
1344 "TARGET_THUMB2 && optimize_size"
1345 "muls\\t%0, %2, %0"
1346 [(set_attr "length" "2")
1347 (set_attr "type" "muls")])
1348
1349 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1350 [(set (reg:CC_NOOV CC_REGNUM)
1351 (compare:CC_NOOV
1352 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1353 (match_operand:SI 2 "register_operand" "l"))
1354 (const_int 0)))
1355 (clobber (match_scratch:SI 0 "=l"))]
1356 "TARGET_THUMB2 && optimize_size"
1357 "muls\\t%0, %2, %0"
1358 [(set_attr "length" "2")
1359 (set_attr "type" "muls")])
1360
1361 (define_insn "*thumb2_cbz"
1362 [(set (pc) (if_then_else
1363 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1364 (const_int 0))
1365 (label_ref (match_operand 1 "" ""))
1366 (pc)))
1367 (clobber (reg:CC CC_REGNUM))]
1368 "TARGET_THUMB2"
1369 "*
1370 if (get_attr_length (insn) == 2)
1371 return \"cbz\\t%0, %l1\";
1372 else
1373 return \"cmp\\t%0, #0\;beq\\t%l1\";
1374 "
1375 [(set (attr "length")
1376 (if_then_else
1377 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1378 (le (minus (match_dup 1) (pc)) (const_int 128))
1379 (not (match_test "which_alternative")))
1380 (const_int 2)
1381 (const_int 8)))
1382 (set_attr "type" "branch,multiple")]
1383 )
1384
1385 (define_insn "*thumb2_cbnz"
1386 [(set (pc) (if_then_else
1387 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1388 (const_int 0))
1389 (label_ref (match_operand 1 "" ""))
1390 (pc)))
1391 (clobber (reg:CC CC_REGNUM))]
1392 "TARGET_THUMB2"
1393 "*
1394 if (get_attr_length (insn) == 2)
1395 return \"cbnz\\t%0, %l1\";
1396 else
1397 return \"cmp\\t%0, #0\;bne\\t%l1\";
1398 "
1399 [(set (attr "length")
1400 (if_then_else
1401 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1402 (le (minus (match_dup 1) (pc)) (const_int 128))
1403 (not (match_test "which_alternative")))
1404 (const_int 2)
1405 (const_int 8)))
1406 (set_attr "type" "branch,multiple")]
1407 )
1408
1409 (define_insn "*thumb2_one_cmplsi2_short"
1410 [(set (match_operand:SI 0 "low_register_operand" "=l")
1411 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1412 (clobber (reg:CC CC_REGNUM))]
1413 "TARGET_THUMB2 && reload_completed"
1414 "mvn%!\t%0, %1"
1415 [(set_attr "predicable" "yes")
1416 (set_attr "length" "2")
1417 (set_attr "type" "mvn_reg")]
1418 )
1419
1420 (define_insn "*thumb2_negsi2_short"
1421 [(set (match_operand:SI 0 "low_register_operand" "=l")
1422 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1423 (clobber (reg:CC CC_REGNUM))]
1424 "TARGET_THUMB2 && reload_completed"
1425 "neg%!\t%0, %1"
1426 [(set_attr "predicable" "yes")
1427 (set_attr "length" "2")
1428 (set_attr "type" "alu_sreg")]
1429 )
1430
1431 ; Constants for op 2 will never be given to these patterns.
1432 (define_insn_and_split "*iordi_notdi_di"
1433 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1434 (ior:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
1435 (match_operand:DI 2 "s_register_operand" "r,0")))]
1436 "TARGET_THUMB2"
1437 "#"
1438 "TARGET_THUMB2 && reload_completed"
1439 [(set (match_dup 0) (ior:SI (not:SI (match_dup 1)) (match_dup 2)))
1440 (set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))]
1441 "
1442 {
1443 operands[3] = gen_highpart (SImode, operands[0]);
1444 operands[0] = gen_lowpart (SImode, operands[0]);
1445 operands[4] = gen_highpart (SImode, operands[1]);
1446 operands[1] = gen_lowpart (SImode, operands[1]);
1447 operands[5] = gen_highpart (SImode, operands[2]);
1448 operands[2] = gen_lowpart (SImode, operands[2]);
1449 }"
1450 [(set_attr "length" "8")
1451 (set_attr "predicable" "yes")
1452 (set_attr "predicable_short_it" "no")
1453 (set_attr "type" "multiple")]
1454 )
1455
1456 (define_insn_and_split "*iordi_notzesidi_di"
1457 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1458 (ior:DI (not:DI (zero_extend:DI
1459 (match_operand:SI 2 "s_register_operand" "r,r")))
1460 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1461 "TARGET_THUMB2"
1462 "#"
1463 ; (not (zero_extend...)) means operand0 will always be 0xffffffff
1464 "TARGET_THUMB2 && reload_completed"
1465 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1466 (set (match_dup 3) (const_int -1))]
1467 "
1468 {
1469 operands[3] = gen_highpart (SImode, operands[0]);
1470 operands[0] = gen_lowpart (SImode, operands[0]);
1471 operands[1] = gen_lowpart (SImode, operands[1]);
1472 }"
1473 [(set_attr "length" "4,8")
1474 (set_attr "predicable" "yes")
1475 (set_attr "predicable_short_it" "no")
1476 (set_attr "type" "multiple")]
1477 )
1478
1479 (define_insn_and_split "*iordi_notdi_zesidi"
1480 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1481 (ior:DI (not:DI (match_operand:DI 2 "s_register_operand" "0,?r"))
1482 (zero_extend:DI
1483 (match_operand:SI 1 "s_register_operand" "r,r"))))]
1484 "TARGET_THUMB2"
1485 "#"
1486 "TARGET_THUMB2 && reload_completed"
1487 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1488 (set (match_dup 3) (not:SI (match_dup 4)))]
1489 "
1490 {
1491 operands[3] = gen_highpart (SImode, operands[0]);
1492 operands[0] = gen_lowpart (SImode, operands[0]);
1493 operands[1] = gen_lowpart (SImode, operands[1]);
1494 operands[4] = gen_highpart (SImode, operands[2]);
1495 operands[2] = gen_lowpart (SImode, operands[2]);
1496 }"
1497 [(set_attr "length" "8")
1498 (set_attr "predicable" "yes")
1499 (set_attr "predicable_short_it" "no")
1500 (set_attr "type" "multiple")]
1501 )
1502
1503 (define_insn_and_split "*iordi_notsesidi_di"
1504 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1505 (ior:DI (not:DI (sign_extend:DI
1506 (match_operand:SI 2 "s_register_operand" "r,r")))
1507 (match_operand:DI 1 "s_register_operand" "0,r")))]
1508 "TARGET_THUMB2"
1509 "#"
1510 "TARGET_THUMB2 && reload_completed"
1511 [(set (match_dup 0) (ior:SI (not:SI (match_dup 2)) (match_dup 1)))
1512 (set (match_dup 3) (ior:SI (not:SI
1513 (ashiftrt:SI (match_dup 2) (const_int 31)))
1514 (match_dup 4)))]
1515 "
1516 {
1517 operands[3] = gen_highpart (SImode, operands[0]);
1518 operands[0] = gen_lowpart (SImode, operands[0]);
1519 operands[4] = gen_highpart (SImode, operands[1]);
1520 operands[1] = gen_lowpart (SImode, operands[1]);
1521 }"
1522 [(set_attr "length" "8")
1523 (set_attr "predicable" "yes")
1524 (set_attr "predicable_short_it" "no")
1525 (set_attr "type" "multiple")]
1526 )
1527
1528 (define_insn "*orsi_notsi_si"
1529 [(set (match_operand:SI 0 "s_register_operand" "=r")
1530 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1531 (match_operand:SI 1 "s_register_operand" "r")))]
1532 "TARGET_THUMB2"
1533 "orn%?\\t%0, %1, %2"
1534 [(set_attr "predicable" "yes")
1535 (set_attr "type" "logic_reg")]
1536 )
1537
1538 (define_insn "*orsi_not_shiftsi_si"
1539 [(set (match_operand:SI 0 "s_register_operand" "=r")
1540 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1541 [(match_operand:SI 2 "s_register_operand" "r")
1542 (match_operand:SI 3 "const_int_operand" "M")]))
1543 (match_operand:SI 1 "s_register_operand" "r")))]
1544 "TARGET_THUMB2"
1545 "orn%?\\t%0, %1, %2%S4"
1546 [(set_attr "predicable" "yes")
1547 (set_attr "shift" "2")
1548 (set_attr "type" "alu_shift_imm")]
1549 )
1550
1551 (define_peephole2
1552 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1553 (compare:CC_NOOV (zero_extract:SI
1554 (match_operand:SI 1 "low_register_operand" "")
1555 (const_int 1)
1556 (match_operand:SI 2 "const_int_operand" ""))
1557 (const_int 0)))
1558 (match_scratch:SI 3 "l")
1559 (set (pc)
1560 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1561 [(match_dup 0) (const_int 0)])
1562 (match_operand 5 "" "")
1563 (match_operand 6 "" "")))]
1564 "TARGET_THUMB2
1565 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1566 && peep2_reg_dead_p (2, operands[0])"
1567 [(parallel [(set (match_dup 0)
1568 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1569 (const_int 0)))
1570 (clobber (match_dup 3))])
1571 (set (pc)
1572 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1573 (match_dup 5) (match_dup 6)))]
1574 "
1575 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1576 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1577 VOIDmode, operands[0], const0_rtx);
1578 ")
1579
1580 (define_peephole2
1581 [(set (match_operand:CC_NOOV 0 "cc_register" "")
1582 (compare:CC_NOOV (zero_extract:SI
1583 (match_operand:SI 1 "low_register_operand" "")
1584 (match_operand:SI 2 "const_int_operand" "")
1585 (const_int 0))
1586 (const_int 0)))
1587 (match_scratch:SI 3 "l")
1588 (set (pc)
1589 (if_then_else (match_operator:CC_NOOV 4 "equality_operator"
1590 [(match_dup 0) (const_int 0)])
1591 (match_operand 5 "" "")
1592 (match_operand 6 "" "")))]
1593 "TARGET_THUMB2
1594 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1595 && peep2_reg_dead_p (2, operands[0])"
1596 [(parallel [(set (match_dup 0)
1597 (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1598 (const_int 0)))
1599 (clobber (match_dup 3))])
1600 (set (pc)
1601 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1602 (match_dup 5) (match_dup 6)))]
1603 "
1604 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1605 ")
1606
1607 ;; Define the subtract-one-and-jump insns so loop.c
1608 ;; knows what to generate.
1609 (define_expand "doloop_end"
1610 [(use (match_operand 0 "" "")) ; loop pseudo
1611 (use (match_operand 1 "" ""))] ; label
1612 "TARGET_32BIT"
1613 "
1614 {
1615 /* Currently SMS relies on the do-loop pattern to recognize loops
1616 where (1) the control part consists of all insns defining and/or
1617 using a certain 'count' register and (2) the loop count can be
1618 adjusted by modifying this register prior to the loop.
1619 ??? The possible introduction of a new block to initialize the
1620 new IV can potentially affect branch optimizations. */
1621 if (optimize > 0 && flag_modulo_sched)
1622 {
1623 rtx s0;
1624 rtx bcomp;
1625 rtx loc_ref;
1626 rtx cc_reg;
1627 rtx insn;
1628 rtx cmp;
1629
1630 if (GET_MODE (operands[0]) != SImode)
1631 FAIL;
1632
1633 s0 = operands [0];
1634 if (TARGET_THUMB2)
1635 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1636 else
1637 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1638
1639 cmp = XVECEXP (PATTERN (insn), 0, 0);
1640 cc_reg = SET_DEST (cmp);
1641 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1642 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1643 emit_jump_insn (gen_rtx_SET (pc_rtx,
1644 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1645 loc_ref, pc_rtx)));
1646 DONE;
1647 }else
1648 FAIL;
1649 }")
1650