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