]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/thumb2.md
[PATCH 4/5][Arm] New pattern for CSNEG instructions
[thirdparty/gcc.git] / gcc / config / arm / thumb2.md
1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2020 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 (const_string "alu_shift_imm")
1265 (const_string "alu_shift_reg")))]
1266 )
1267
1268 (define_insn "*thumb2_mov<mode>_shortim"
1269 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1270 (match_operand:QHSI 1 "const_int_operand" "I"))
1271 (clobber (reg:CC CC_REGNUM))]
1272 "TARGET_THUMB2 && reload_completed"
1273 "mov%!\t%0, %1"
1274 [(set_attr "predicable" "yes")
1275 (set_attr "length" "2")
1276 (set_attr "type" "mov_imm")]
1277 )
1278
1279 (define_insn "*thumb2_addsi_short"
1280 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1281 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1282 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1283 (clobber (reg:CC CC_REGNUM))]
1284 "TARGET_THUMB2 && reload_completed"
1285 "*
1286 HOST_WIDE_INT val;
1287
1288 if (CONST_INT_P (operands[2]))
1289 val = INTVAL(operands[2]);
1290 else
1291 val = 0;
1292
1293 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
1294 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1295 return \"sub%!\\t%0, %1, #%n2\";
1296 else
1297 return \"add%!\\t%0, %1, %2\";
1298 "
1299 [(set_attr "predicable" "yes")
1300 (set_attr "length" "2")
1301 (set_attr_alternative "type"
1302 [(if_then_else (match_operand 2 "const_int_operand" "")
1303 (const_string "alu_imm")
1304 (const_string "alu_sreg"))
1305 (const_string "alu_imm")])]
1306 )
1307
1308 (define_insn "*thumb2_subsi_short"
1309 [(set (match_operand:SI 0 "low_register_operand" "=l")
1310 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1311 (match_operand:SI 2 "low_register_operand" "l")))
1312 (clobber (reg:CC CC_REGNUM))]
1313 "TARGET_THUMB2 && reload_completed"
1314 "sub%!\\t%0, %1, %2"
1315 [(set_attr "predicable" "yes")
1316 (set_attr "length" "2")
1317 (set_attr "type" "alu_sreg")]
1318 )
1319
1320 (define_peephole2
1321 [(set (match_operand:CC 0 "cc_register" "")
1322 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1323 (match_operand:SI 2 "const_int_operand" "")))]
1324 "TARGET_THUMB2
1325 && peep2_reg_dead_p (1, operands[1])
1326 && satisfies_constraint_Pw (operands[2])"
1327 [(parallel
1328 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1329 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1330 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1331 )
1332
1333 (define_peephole2
1334 [(match_scratch:SI 3 "l")
1335 (set (match_operand:CC 0 "cc_register" "")
1336 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1337 (match_operand:SI 2 "const_int_operand" "")))]
1338 "TARGET_THUMB2
1339 && satisfies_constraint_Px (operands[2])"
1340 [(parallel
1341 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1342 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1343 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1344 )
1345
1346 (define_insn "thumb2_addsi3_compare0"
1347 [(set (reg:CC_NZ CC_REGNUM)
1348 (compare:CC_NZ
1349 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1350 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1351 (const_int 0)))
1352 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1353 (plus:SI (match_dup 1) (match_dup 2)))]
1354 "TARGET_THUMB2"
1355 "*
1356 HOST_WIDE_INT val;
1357
1358 if (CONST_INT_P (operands[2]))
1359 val = INTVAL (operands[2]);
1360 else
1361 val = 0;
1362
1363 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1364 return \"subs\\t%0, %1, #%n2\";
1365 else
1366 return \"adds\\t%0, %1, %2\";
1367 "
1368 [(set_attr "conds" "set")
1369 (set_attr "length" "2,2,4")
1370 (set_attr_alternative "type"
1371 [(if_then_else (match_operand 2 "const_int_operand" "")
1372 (const_string "alus_imm")
1373 (const_string "alus_sreg"))
1374 (const_string "alus_imm")
1375 (if_then_else (match_operand 2 "const_int_operand" "")
1376 (const_string "alus_imm")
1377 (const_string "alus_sreg"))])]
1378 )
1379
1380 (define_insn "*thumb2_addsi3_compare0_scratch"
1381 [(set (reg:CC_NZ CC_REGNUM)
1382 (compare:CC_NZ
1383 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r")
1384 (match_operand:SI 1 "arm_add_operand" "lPv,rIL"))
1385 (const_int 0)))]
1386 "TARGET_THUMB2"
1387 "*
1388 HOST_WIDE_INT val;
1389
1390 if (CONST_INT_P (operands[1]))
1391 val = INTVAL (operands[1]);
1392 else
1393 val = 0;
1394
1395 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1396 return \"cmp\\t%0, #%n1\";
1397 else
1398 return \"cmn\\t%0, %1\";
1399 "
1400 [(set_attr "conds" "set")
1401 (set_attr "length" "2,4")
1402 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1403 (const_string "alus_imm")
1404 (const_string "alus_sreg")))]
1405 )
1406
1407 (define_insn "*thumb2_mulsi_short"
1408 [(set (match_operand:SI 0 "low_register_operand" "=l")
1409 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1410 (match_operand:SI 2 "low_register_operand" "l")))
1411 (clobber (reg:CC CC_REGNUM))]
1412 "TARGET_THUMB2 && optimize_size && reload_completed"
1413 "mul%!\\t%0, %2, %0"
1414 [(set_attr "predicable" "yes")
1415 (set_attr "length" "2")
1416 (set_attr "type" "muls")])
1417
1418 (define_insn "*thumb2_mulsi_short_compare0"
1419 [(set (reg:CC_NZ CC_REGNUM)
1420 (compare:CC_NZ
1421 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1422 (match_operand:SI 2 "register_operand" "l"))
1423 (const_int 0)))
1424 (set (match_operand:SI 0 "register_operand" "=l")
1425 (mult:SI (match_dup 1) (match_dup 2)))]
1426 "TARGET_THUMB2 && optimize_size"
1427 "muls\\t%0, %2, %0"
1428 [(set_attr "length" "2")
1429 (set_attr "type" "muls")])
1430
1431 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1432 [(set (reg:CC_NZ CC_REGNUM)
1433 (compare:CC_NZ
1434 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1435 (match_operand:SI 2 "register_operand" "l"))
1436 (const_int 0)))
1437 (clobber (match_scratch:SI 0 "=l"))]
1438 "TARGET_THUMB2 && optimize_size"
1439 "muls\\t%0, %2, %0"
1440 [(set_attr "length" "2")
1441 (set_attr "type" "muls")])
1442
1443 (define_insn "*thumb2_cbz"
1444 [(set (pc) (if_then_else
1445 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1446 (const_int 0))
1447 (label_ref (match_operand 1 "" ""))
1448 (pc)))
1449 (clobber (reg:CC CC_REGNUM))]
1450 "TARGET_THUMB2"
1451 "*
1452 if (get_attr_length (insn) == 2)
1453 return \"cbz\\t%0, %l1\";
1454 else
1455 return \"cmp\\t%0, #0\;beq\\t%l1\";
1456 "
1457 [(set (attr "length")
1458 (if_then_else
1459 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1460 (le (minus (match_dup 1) (pc)) (const_int 128))
1461 (not (match_test "which_alternative")))
1462 (const_int 2)
1463 (const_int 8)))
1464 (set_attr "type" "branch,multiple")]
1465 )
1466
1467 (define_insn "*thumb2_cbnz"
1468 [(set (pc) (if_then_else
1469 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1470 (const_int 0))
1471 (label_ref (match_operand 1 "" ""))
1472 (pc)))
1473 (clobber (reg:CC CC_REGNUM))]
1474 "TARGET_THUMB2"
1475 "*
1476 if (get_attr_length (insn) == 2)
1477 return \"cbnz\\t%0, %l1\";
1478 else
1479 return \"cmp\\t%0, #0\;bne\\t%l1\";
1480 "
1481 [(set (attr "length")
1482 (if_then_else
1483 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1484 (le (minus (match_dup 1) (pc)) (const_int 128))
1485 (not (match_test "which_alternative")))
1486 (const_int 2)
1487 (const_int 8)))
1488 (set_attr "type" "branch,multiple")]
1489 )
1490
1491 (define_insn "*thumb2_one_cmplsi2_short"
1492 [(set (match_operand:SI 0 "low_register_operand" "=l")
1493 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1494 (clobber (reg:CC CC_REGNUM))]
1495 "TARGET_THUMB2 && reload_completed"
1496 "mvn%!\t%0, %1"
1497 [(set_attr "predicable" "yes")
1498 (set_attr "length" "2")
1499 (set_attr "type" "mvn_reg")]
1500 )
1501
1502 (define_insn "*thumb2_negsi2_short"
1503 [(set (match_operand:SI 0 "low_register_operand" "=l")
1504 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1505 (clobber (reg:CC CC_REGNUM))]
1506 "TARGET_THUMB2 && reload_completed"
1507 "rsb%!\t%0, %1, #0"
1508 [(set_attr "predicable" "yes")
1509 (set_attr "length" "2")
1510 (set_attr "type" "alu_sreg")]
1511 )
1512
1513 (define_insn "*orsi_notsi_si"
1514 [(set (match_operand:SI 0 "s_register_operand" "=r")
1515 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1516 (match_operand:SI 1 "s_register_operand" "r")))]
1517 "TARGET_THUMB2"
1518 "orn%?\\t%0, %1, %2"
1519 [(set_attr "predicable" "yes")
1520 (set_attr "type" "logic_reg")]
1521 )
1522
1523 (define_insn "*orsi_not_shiftsi_si"
1524 [(set (match_operand:SI 0 "s_register_operand" "=r")
1525 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1526 [(match_operand:SI 2 "s_register_operand" "r")
1527 (match_operand:SI 3 "const_int_operand" "M")]))
1528 (match_operand:SI 1 "s_register_operand" "r")))]
1529 "TARGET_THUMB2"
1530 "orn%?\\t%0, %1, %2%S4"
1531 [(set_attr "predicable" "yes")
1532 (set_attr "shift" "2")
1533 (set_attr "type" "alu_shift_imm")]
1534 )
1535
1536 (define_peephole2
1537 [(set (match_operand:CC_NZ 0 "cc_register" "")
1538 (compare:CC_NZ (zero_extract:SI
1539 (match_operand:SI 1 "low_register_operand" "")
1540 (const_int 1)
1541 (match_operand:SI 2 "const_int_operand" ""))
1542 (const_int 0)))
1543 (match_scratch:SI 3 "l")
1544 (set (pc)
1545 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1546 [(match_dup 0) (const_int 0)])
1547 (match_operand 5 "" "")
1548 (match_operand 6 "" "")))]
1549 "TARGET_THUMB2
1550 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1551 && peep2_reg_dead_p (2, operands[0])"
1552 [(parallel [(set (match_dup 0)
1553 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1554 (const_int 0)))
1555 (clobber (match_dup 3))])
1556 (set (pc)
1557 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1558 (match_dup 5) (match_dup 6)))]
1559 "
1560 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1561 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1562 VOIDmode, operands[0], const0_rtx);
1563 ")
1564
1565 (define_peephole2
1566 [(set (match_operand:CC_NZ 0 "cc_register" "")
1567 (compare:CC_NZ (zero_extract:SI
1568 (match_operand:SI 1 "low_register_operand" "")
1569 (match_operand:SI 2 "const_int_operand" "")
1570 (const_int 0))
1571 (const_int 0)))
1572 (match_scratch:SI 3 "l")
1573 (set (pc)
1574 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1575 [(match_dup 0) (const_int 0)])
1576 (match_operand 5 "" "")
1577 (match_operand 6 "" "")))]
1578 "TARGET_THUMB2
1579 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1580 && peep2_reg_dead_p (2, operands[0])"
1581 [(parallel [(set (match_dup 0)
1582 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1583 (const_int 0)))
1584 (clobber (match_dup 3))])
1585 (set (pc)
1586 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1587 (match_dup 5) (match_dup 6)))]
1588 "
1589 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1590 ")
1591
1592 ;; Define the subtract-one-and-jump insns so loop.c
1593 ;; knows what to generate.
1594 (define_expand "doloop_end"
1595 [(use (match_operand 0 "" "")) ; loop pseudo
1596 (use (match_operand 1 "" ""))] ; label
1597 "TARGET_32BIT"
1598 "
1599 {
1600 /* Currently SMS relies on the do-loop pattern to recognize loops
1601 where (1) the control part consists of all insns defining and/or
1602 using a certain 'count' register and (2) the loop count can be
1603 adjusted by modifying this register prior to the loop.
1604 ??? The possible introduction of a new block to initialize the
1605 new IV can potentially affect branch optimizations.
1606
1607 Also used to implement the low over head loops feature, which is part of
1608 the Armv8.1-M Mainline Low Overhead Branch (LOB) extension. */
1609 if (optimize > 0 && (flag_modulo_sched || TARGET_HAVE_LOB))
1610 {
1611 rtx s0;
1612 rtx bcomp;
1613 rtx loc_ref;
1614 rtx cc_reg;
1615 rtx insn;
1616 rtx cmp;
1617
1618 if (GET_MODE (operands[0]) != SImode)
1619 FAIL;
1620
1621 s0 = operands [0];
1622
1623 /* Low over head loop instructions require the first operand to be LR. */
1624 if (TARGET_HAVE_LOB && arm_target_insn_ok_for_lob (operands [1]))
1625 s0 = gen_rtx_REG (SImode, LR_REGNUM);
1626
1627 if (TARGET_THUMB2)
1628 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1629 else
1630 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1631
1632 cmp = XVECEXP (PATTERN (insn), 0, 0);
1633 cc_reg = SET_DEST (cmp);
1634 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1635 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1636 emit_jump_insn (gen_rtx_SET (pc_rtx,
1637 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1638 loc_ref, pc_rtx)));
1639 DONE;
1640 }
1641 else
1642 FAIL;
1643 }")
1644
1645 (define_insn "*clear_apsr"
1646 [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1647 (clobber (reg:CC CC_REGNUM))]
1648 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1649 "clrm%?\\t{APSR}"
1650 [(set_attr "predicable" "yes")]
1651 )
1652
1653 ;; The operands are validated through the clear_multiple_operation
1654 ;; match_parallel predicate rather than through constraints so enable it only
1655 ;; after reload.
1656 (define_insn "*clear_multiple"
1657 [(match_parallel 0 "clear_multiple_operation"
1658 [(set (match_operand:SI 1 "register_operand" "")
1659 (const_int 0))])]
1660 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1661 {
1662 char pattern[100];
1663 int i, num_saves = XVECLEN (operands[0], 0);
1664
1665 strcpy (pattern, \"clrm%?\\t{\");
1666 for (i = 0; i < num_saves; i++)
1667 {
1668 if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1669 {
1670 strcat (pattern, \"APSR\");
1671 ++i;
1672 }
1673 else
1674 strcat (pattern,
1675 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1676 if (i < num_saves - 1)
1677 strcat (pattern, \", %|\");
1678 }
1679 strcat (pattern, \"}\");
1680 output_asm_insn (pattern, operands);
1681 return \"\";
1682 }
1683 [(set_attr "predicable" "yes")]
1684 )
1685
1686 (define_insn "thumb2_asrl"
1687 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1688 (ashiftrt:DI (match_dup 0)
1689 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1690 "TARGET_HAVE_MVE"
1691 "asrl%?\\t%Q0, %R0, %1"
1692 [(set_attr "predicable" "yes")])
1693
1694 (define_insn "thumb2_lsll"
1695 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1696 (ashift:DI (match_dup 0)
1697 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1698 "TARGET_HAVE_MVE"
1699 "lsll%?\\t%Q0, %R0, %1"
1700 [(set_attr "predicable" "yes")])
1701
1702 (define_insn "thumb2_lsrl"
1703 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1704 (lshiftrt:DI (match_dup 0)
1705 (match_operand:SI 1 "long_shift_imm" "Pg")))]
1706 "TARGET_HAVE_MVE"
1707 "lsrl%?\\t%Q0, %R0, %1"
1708 [(set_attr "predicable" "yes")])
1709
1710 ;; Originally expanded by 'doloop_end'.
1711 (define_insn "*doloop_end_internal"
1712 [(parallel [(set (pc)
1713 (if_then_else
1714 (ne (reg:SI LR_REGNUM) (const_int 1))
1715 (label_ref (match_operand 0 "" ""))
1716 (pc)))
1717 (set (reg:SI LR_REGNUM)
1718 (plus:SI (reg:SI LR_REGNUM) (const_int -1)))])]
1719 "TARGET_32BIT && TARGET_HAVE_LOB"
1720 "le\t%|lr, %l0")
1721
1722 (define_expand "doloop_begin"
1723 [(match_operand 0 "" "")
1724 (match_operand 1 "" "")]
1725 "TARGET_32BIT && TARGET_HAVE_LOB"
1726 {
1727 if (REGNO (operands[0]) == LR_REGNUM)
1728 {
1729 emit_insn (gen_dls_insn (operands[0]));
1730 DONE;
1731 }
1732 else
1733 FAIL;
1734 })
1735
1736 (define_insn "dls_insn"
1737 [(set (reg:SI LR_REGNUM)
1738 (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))]
1739 "TARGET_32BIT && TARGET_HAVE_LOB"
1740 "dls\t%|lr, %0")