]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/arm/thumb2.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / arm / thumb2.md
1 ;; ARM Thumb-2 Machine Description
2 ;; Copyright (C) 2007-2022 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_fpcxt"
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 && TARGET_HAVE_FPCXT_CMSE"
546 "blxns\\t%0"
547 [(set_attr "length" "4")
548 (set_attr "type" "call")]
549 )
550
551 (define_insn "*nonsecure_call_reg_thumb2"
552 [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
553 UNSPEC_NONSECURE_MEM)
554 (match_operand 0 "" ""))
555 (use (match_operand 1 "" ""))
556 (clobber (reg:SI LR_REGNUM))]
557 "TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE"
558 "bl\\t__gnu_cmse_nonsecure_call"
559 [(set_attr "length" "4")
560 (set_attr "type" "call")]
561 )
562
563 (define_insn "*call_value_reg_thumb2"
564 [(set (match_operand 0 "" "")
565 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
566 (match_operand 2 "" "")))
567 (use (match_operand 3 "" ""))
568 (clobber (reg:SI LR_REGNUM))]
569 "TARGET_THUMB2"
570 "blx\\t%1"
571 [(set_attr "type" "call")]
572 )
573
574 (define_insn "*nonsecure_call_value_reg_thumb2_fpcxt"
575 [(set (match_operand 0 "" "")
576 (call
577 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
578 UNSPEC_NONSECURE_MEM)
579 (match_operand 2 "" "")))
580 (use (match_operand 3 "" ""))
581 (clobber (reg:SI LR_REGNUM))]
582 "TARGET_THUMB2 && use_cmse && TARGET_HAVE_FPCXT_CMSE"
583 "blxns\\t%1"
584 [(set_attr "length" "4")
585 (set_attr "type" "call")]
586 )
587
588 (define_insn "*nonsecure_call_value_reg_thumb2"
589 [(set (match_operand 0 "" "")
590 (call
591 (unspec:SI [(mem:SI (reg:SI R4_REGNUM))] UNSPEC_NONSECURE_MEM)
592 (match_operand 1 "" "")))
593 (use (match_operand 2 "" ""))
594 (clobber (reg:SI LR_REGNUM))]
595 "TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE"
596 "bl\\t__gnu_cmse_nonsecure_call"
597 [(set_attr "length" "4")
598 (set_attr "type" "call")]
599 )
600
601 (define_insn "*thumb2_indirect_jump"
602 [(set (pc)
603 (match_operand:SI 0 "register_operand" "l*r"))]
604 "TARGET_THUMB2"
605 "bx\\t%0"
606 [(set_attr "conds" "clob")
607 (set_attr "type" "branch")]
608 )
609 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label
610 ;; addresses will have the thumb bit set correctly.
611
612
613 (define_insn_and_split "*thumb2_and_scc"
614 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
615 (and:SI (match_operator:SI 1 "arm_comparison_operator"
616 [(match_operand 2 "cc_register" "") (const_int 0)])
617 (match_operand:SI 3 "s_register_operand" "r")))]
618 "TARGET_THUMB2"
619 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
620 "&& reload_completed"
621 [(set (match_dup 0)
622 (and:SI (match_dup 3) (const_int 1)))
623 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))]
624 {
625 machine_mode mode = GET_MODE (operands[2]);
626 enum rtx_code rc = GET_CODE (operands[1]);
627
628 if (mode == CCFPmode || mode == CCFPEmode)
629 rc = reverse_condition_maybe_unordered (rc);
630 else
631 rc = reverse_condition (rc);
632 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
633 }
634 [(set_attr "conds" "use")
635 (set_attr "type" "multiple")
636 (set (attr "length") (if_then_else (match_test "arm_restrict_it")
637 (const_int 8)
638 (const_int 10)))]
639 )
640
641 (define_insn_and_split "*thumb2_ior_scc"
642 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
643 (ior:SI (match_operator:SI 1 "arm_comparison_operator"
644 [(match_operand 2 "cc_register" "") (const_int 0)])
645 (match_operand:SI 3 "s_register_operand" "0,?r")))]
646 "TARGET_THUMB2 && !arm_restrict_it"
647 "@
648 it\\t%d1\;orr%d1\\t%0, %3, #1
649 #"
650 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
651 "&& reload_completed
652 && REGNO (operands [0]) != REGNO (operands[3])"
653 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
654 (cond_exec (match_dup 4) (set (match_dup 0)
655 (ior:SI (match_dup 3) (const_int 1))))]
656 {
657 machine_mode mode = GET_MODE (operands[2]);
658 enum rtx_code rc = GET_CODE (operands[1]);
659
660 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
661 if (mode == CCFPmode || mode == CCFPEmode)
662 rc = reverse_condition_maybe_unordered (rc);
663 else
664 rc = reverse_condition (rc);
665 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
666 }
667 [(set_attr "conds" "use")
668 (set_attr "length" "6,10")
669 (set_attr "type" "multiple")]
670 )
671
672 (define_insn_and_split "*thumb2_ior_scc_strict_it"
673 [(set (match_operand:SI 0 "s_register_operand" "=&r")
674 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
675 [(match_operand 3 "cc_register" "") (const_int 0)])
676 (match_operand:SI 1 "s_register_operand" "r")))]
677 "TARGET_THUMB2 && arm_restrict_it"
678 "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1
679 "&& reload_completed"
680 [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1)))
681 (cond_exec (match_dup 4)
682 (set (match_dup 0) (match_dup 1)))]
683 {
684 machine_mode mode = GET_MODE (operands[3]);
685 rtx_code rc = GET_CODE (operands[2]);
686
687 if (mode == CCFPmode || mode == CCFPEmode)
688 rc = reverse_condition_maybe_unordered (rc);
689 else
690 rc = reverse_condition (rc);
691 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
692 }
693 [(set_attr "conds" "use")
694 (set_attr "length" "8")
695 (set_attr "type" "multiple")]
696 )
697
698 (define_insn "*thumb2_cond_move"
699 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
700 (if_then_else:SI (match_operator 3 "equality_operator"
701 [(match_operator 4 "arm_comparison_operator"
702 [(match_operand 5 "cc_register" "") (const_int 0)])
703 (const_int 0)])
704 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
705 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
706 "TARGET_THUMB2"
707 "*
708 if (GET_CODE (operands[3]) == NE)
709 {
710 if (which_alternative != 1)
711 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands);
712 if (which_alternative != 0)
713 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands);
714 return \"\";
715 }
716 switch (which_alternative)
717 {
718 case 0:
719 output_asm_insn (\"it\\t%d4\", operands);
720 break;
721 case 1:
722 output_asm_insn (\"it\\t%D4\", operands);
723 break;
724 case 2:
725 if (arm_restrict_it)
726 output_asm_insn (\"it\\t%D4\", operands);
727 else
728 output_asm_insn (\"ite\\t%D4\", operands);
729 break;
730 default:
731 abort();
732 }
733 if (which_alternative != 0)
734 {
735 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
736 if (arm_restrict_it && which_alternative == 2)
737 output_asm_insn (\"it\\t%d4\", operands);
738 }
739 if (which_alternative != 1)
740 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
741 return \"\";
742 "
743 [(set_attr "conds" "use")
744 (set_attr "length" "6,6,10")
745 (set_attr "type" "multiple")]
746 )
747
748 (define_insn "*thumb2_cond_arith"
749 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
750 (match_operator:SI 5 "shiftable_operator"
751 [(match_operator:SI 4 "arm_comparison_operator"
752 [(match_operand:SI 2 "s_register_operand" "r,r")
753 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
754 (match_operand:SI 1 "s_register_operand" "0,?r")]))
755 (clobber (reg:CC CC_REGNUM))]
756 "TARGET_THUMB2 && !arm_restrict_it"
757 "*
758 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
759 return \"%i5\\t%0, %1, %2, lsr #31\";
760
761 output_asm_insn (\"cmp\\t%2, %3\", operands);
762
763 if (GET_CODE (operands[5]) == PLUS && TARGET_COND_ARITH)
764 return \"cinc\\t%0, %1, %d4\";
765
766 if (GET_CODE (operands[5]) == AND)
767 {
768 output_asm_insn (\"ite\\t%D4\", operands);
769 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
770 }
771 else if (GET_CODE (operands[5]) == MINUS)
772 {
773 output_asm_insn (\"ite\\t%D4\", operands);
774 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
775 }
776 else if (which_alternative != 0)
777 {
778 output_asm_insn (\"ite\\t%D4\", operands);
779 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
780 }
781 else
782 output_asm_insn (\"it\\t%d4\", operands);
783 return \"%i5%d4\\t%0, %1, #1\";
784 "
785 [(set_attr "conds" "clob")
786 (set_attr "length" "14")
787 (set_attr "type" "multiple")]
788 )
789
790 (define_insn_and_split "*thumb2_cond_arith_strict_it"
791 [(set (match_operand:SI 0 "s_register_operand" "=l")
792 (match_operator:SI 5 "shiftable_operator_strict_it"
793 [(match_operator:SI 4 "arm_comparison_operator"
794 [(match_operand:SI 2 "s_register_operand" "r")
795 (match_operand:SI 3 "arm_rhs_operand" "rI")])
796 (match_operand:SI 1 "s_register_operand" "0")]))
797 (clobber (reg:CC CC_REGNUM))]
798 "TARGET_THUMB2 && arm_restrict_it"
799 "#"
800 "&& reload_completed"
801 [(const_int 0)]
802 {
803 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
804 {
805 /* %i5 %0, %1, %2, lsr #31 */
806 rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
807 rtx op = NULL_RTX;
808
809 switch (GET_CODE (operands[5]))
810 {
811 case AND:
812 op = gen_rtx_AND (SImode, shifted_op, operands[1]);
813 break;
814 case PLUS:
815 op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
816 break;
817 default: gcc_unreachable ();
818 }
819 emit_insn (gen_rtx_SET (operands[0], op));
820 DONE;
821 }
822
823 /* "cmp %2, %3" */
824 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
825 gen_rtx_COMPARE (CCmode, operands[2],
826 operands[3])));
827
828 if (GET_CODE (operands[5]) == AND)
829 {
830 /* %i5 %0, %1, #1
831 it%D4
832 mov%D4 %0, #0 */
833 enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
834 emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
835 GEN_INT (1))));
836 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
837 gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
838 gen_rtx_SET (operands[0], const0_rtx)));
839 DONE;
840 }
841 else
842 {
843 /* it\\t%d4
844 %i5%d4\\t%0, %1, #1 */
845 emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
846 VOIDmode,
847 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
848 gen_rtx_SET (operands[0],
849 gen_rtx_PLUS (SImode,
850 operands[1],
851 GEN_INT (1)))));
852 DONE;
853 }
854 FAIL;
855 }
856 [(set_attr "conds" "clob")
857 (set_attr "length" "12")
858 (set_attr "type" "multiple")]
859 )
860
861 (define_insn "*thumb2_cond_sub"
862 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
863 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
864 (match_operator:SI 4 "arm_comparison_operator"
865 [(match_operand:SI 2 "s_register_operand" "r,r")
866 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
867 (clobber (reg:CC CC_REGNUM))]
868 "TARGET_THUMB2"
869 "*
870 output_asm_insn (\"cmp\\t%2, %3\", operands);
871 if (which_alternative != 0)
872 {
873 if (arm_restrict_it)
874 {
875 output_asm_insn (\"mov\\t%0, %1\", operands);
876 output_asm_insn (\"it\\t%d4\", operands);
877 }
878 else
879 {
880 output_asm_insn (\"ite\\t%D4\", operands);
881 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
882 }
883 }
884 else
885 output_asm_insn (\"it\\t%d4\", operands);
886 return \"sub%d4\\t%0, %1, #1\";
887 "
888 [(set_attr "conds" "clob")
889 (set_attr "length" "10,14")
890 (set_attr "type" "multiple")]
891 )
892
893 (define_insn_and_split "*thumb2_negscc"
894 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
895 (neg:SI (match_operator 3 "arm_comparison_operator"
896 [(match_operand:SI 1 "s_register_operand" "r")
897 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
898 (clobber (reg:CC CC_REGNUM))]
899 "TARGET_THUMB2 && !TARGET_COND_ARITH"
900 "#"
901 "&& reload_completed"
902 [(const_int 0)]
903 {
904 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
905
906 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
907 {
908 /* Emit asr\\t%0, %1, #31 */
909 emit_insn (gen_rtx_SET (operands[0],
910 gen_rtx_ASHIFTRT (SImode,
911 operands[1],
912 GEN_INT (31))));
913 DONE;
914 }
915 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
916 {
917 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
918 if (CONST_INT_P (operands[2]))
919 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
920 gen_int_mode (-INTVAL (operands[2]),
921 SImode)));
922 else
923 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
924
925 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
926 gen_rtx_NE (SImode,
927 cc_reg,
928 const0_rtx),
929 gen_rtx_SET (operands[0],
930 GEN_INT (~0))));
931 DONE;
932 }
933 else
934 {
935 /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
936 enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
937 machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
938 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
939
940 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
941 operands[2])));
942
943 emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
944
945 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
946 gen_rtx_fmt_ee (rc,
947 VOIDmode,
948 tmp1,
949 const0_rtx),
950 gen_rtx_SET (operands[0], const0_rtx)));
951 DONE;
952 }
953 FAIL;
954 }
955 [(set_attr "conds" "clob")
956 (set_attr "length" "14")
957 (set_attr "type" "multiple")]
958 )
959
960 (define_insn "*thumb2_csinv"
961 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
962 (if_then_else:SI
963 (match_operand 1 "arm_comparison_operation" "")
964 (not:SI (match_operand:SI 2 "arm_general_register_operand" "r, r"))
965 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
966 "TARGET_COND_ARITH"
967 "@
968 csinv\\t%0, %3, %2, %D1
969 csinv\\t%0, zr, %2, %D1"
970 [(set_attr "type" "csel")
971 (set_attr "predicable" "no")]
972 )
973
974 (define_insn "*thumb2_csinc"
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 (plus:SI (match_operand:SI 2 "arm_general_register_operand" "r, r")
979 (const_int 1))
980 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
981 "TARGET_COND_ARITH"
982 "@
983 csinc\\t%0, %3, %2, %D1
984 csinc\\t%0, zr, %2, %D1"
985 [(set_attr "type" "csel")
986 (set_attr "predicable" "no")]
987 )
988
989 (define_insn "*thumb2_csneg"
990 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r")
991 (if_then_else:SI
992 (match_operand 1 "arm_comparison_operation" "")
993 (neg:SI (match_operand:SI 2 "arm_general_register_operand" "r, r"))
994 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))]
995 "TARGET_COND_ARITH"
996 "@
997 csneg\\t%0, %3, %2, %D1
998 csneg\\t%0, zr, %2, %D1"
999 [(set_attr "type" "csel")
1000 (set_attr "predicable" "no")]
1001 )
1002
1003 (define_insn "*thumb2_movcond"
1004 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
1005 (if_then_else:SI
1006 (match_operator 5 "arm_comparison_operator"
1007 [(match_operand:SI 3 "s_register_operand" "r,r,r")
1008 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
1009 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
1010 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
1011 (clobber (reg:CC CC_REGNUM))]
1012 "TARGET_THUMB2 && !TARGET_COND_ARITH"
1013 "*
1014 if (GET_CODE (operands[5]) == LT
1015 && (operands[4] == const0_rtx))
1016 {
1017 if (which_alternative != 1 && REG_P (operands[1]))
1018 {
1019 if (operands[2] == const0_rtx)
1020 return \"and\\t%0, %1, %3, asr #31\";
1021 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
1022 }
1023 else if (which_alternative != 0 && REG_P (operands[2]))
1024 {
1025 if (operands[1] == const0_rtx)
1026 return \"bic\\t%0, %2, %3, asr #31\";
1027 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
1028 }
1029 /* The only case that falls through to here is when both ops 1 & 2
1030 are constants. */
1031 }
1032
1033 if (GET_CODE (operands[5]) == GE
1034 && (operands[4] == const0_rtx))
1035 {
1036 if (which_alternative != 1 && REG_P (operands[1]))
1037 {
1038 if (operands[2] == const0_rtx)
1039 return \"bic\\t%0, %1, %3, asr #31\";
1040 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
1041 }
1042 else if (which_alternative != 0 && REG_P (operands[2]))
1043 {
1044 if (operands[1] == const0_rtx)
1045 return \"and\\t%0, %2, %3, asr #31\";
1046 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
1047 }
1048 /* The only case that falls through to here is when both ops 1 & 2
1049 are constants. */
1050 }
1051 if (CONST_INT_P (operands[4])
1052 && !const_ok_for_arm (INTVAL (operands[4])))
1053 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
1054 else
1055 output_asm_insn (\"cmp\\t%3, %4\", operands);
1056 switch (which_alternative)
1057 {
1058 case 0:
1059 output_asm_insn (\"it\\t%D5\", operands);
1060 break;
1061 case 1:
1062 output_asm_insn (\"it\\t%d5\", operands);
1063 break;
1064 case 2:
1065 if (arm_restrict_it)
1066 {
1067 output_asm_insn (\"mov\\t%0, %1\", operands);
1068 output_asm_insn (\"it\\t%D5\", operands);
1069 }
1070 else
1071 output_asm_insn (\"ite\\t%d5\", operands);
1072 break;
1073 default:
1074 abort();
1075 }
1076 if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
1077 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1078 if (which_alternative != 1)
1079 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1080 return \"\";
1081 "
1082 [(set_attr "conds" "clob")
1083 (set_attr "length" "10,10,14")
1084 (set_attr "type" "multiple")]
1085 )
1086
1087 ;; Zero and sign extension instructions.
1088
1089 ;; All supported Thumb2 implementations are armv6, so only that case is
1090 ;; provided.
1091 (define_insn "*thumb2_extendqisi_v6"
1092 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1093 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1094 "TARGET_THUMB2 && arm_arch6"
1095 "@
1096 sxtb%?\\t%0, %1
1097 ldrsb%?\\t%0, %1"
1098 [(set_attr "type" "extend,load_byte")
1099 (set_attr "predicable" "yes")
1100 (set_attr "pool_range" "*,4094")
1101 (set_attr "neg_pool_range" "*,250")]
1102 )
1103
1104 (define_insn "*thumb2_zero_extendhisi2_v6"
1105 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1106 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1107 "TARGET_THUMB2 && arm_arch6"
1108 "@
1109 uxth%?\\t%0, %1
1110 ldrh%?\\t%0, %1"
1111 [(set_attr "type" "extend,load_byte")
1112 (set_attr "predicable" "yes")
1113 (set_attr "pool_range" "*,4094")
1114 (set_attr "neg_pool_range" "*,250")]
1115 )
1116
1117 (define_insn "thumb2_zero_extendqisi2_v6"
1118 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1119 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1120 "TARGET_THUMB2 && arm_arch6"
1121 "@
1122 uxtb%?\\t%0, %1
1123 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1124 [(set_attr "type" "extend,load_byte")
1125 (set_attr "predicable" "yes")
1126 (set_attr "pool_range" "*,4094")
1127 (set_attr "neg_pool_range" "*,250")]
1128 )
1129
1130 (define_expand "thumb2_casesi_internal"
1131 [(parallel [(set (pc)
1132 (if_then_else
1133 (leu (match_operand:SI 0 "s_register_operand")
1134 (match_operand:SI 1 "arm_rhs_operand"))
1135 (match_dup 4)
1136 (label_ref:SI (match_operand 3 ""))))
1137 (clobber (reg:CC CC_REGNUM))
1138 (clobber (match_scratch:SI 5))
1139 (use (label_ref:SI (match_operand 2 "")))])]
1140 "TARGET_THUMB2 && !flag_pic"
1141 {
1142 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1143 operands[4] = gen_rtx_PLUS (SImode, operands[4],
1144 gen_rtx_LABEL_REF (SImode, operands[2]));
1145 operands[4] = gen_rtx_MEM (SImode, operands[4]);
1146 MEM_READONLY_P (operands[4]) = 1;
1147 MEM_NOTRAP_P (operands[4]) = 1;
1148 })
1149
1150 (define_insn "*thumb2_casesi_internal"
1151 [(parallel [(set (pc)
1152 (if_then_else
1153 (leu (match_operand:SI 0 "s_register_operand" "r")
1154 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1155 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1156 (label_ref:SI (match_operand 2 "" ""))))
1157 (label_ref:SI (match_operand 3 "" ""))))
1158 (clobber (reg:CC CC_REGNUM))
1159 (clobber (match_scratch:SI 4 "=&r"))
1160 (use (label_ref:SI (match_dup 2)))])]
1161 "TARGET_THUMB2 && !flag_pic"
1162 "* return thumb2_output_casesi(operands);"
1163 [(set_attr "conds" "clob")
1164 (set_attr "length" "16")
1165 (set_attr "type" "multiple")]
1166 )
1167
1168 (define_expand "thumb2_casesi_internal_pic"
1169 [(parallel [(set (pc)
1170 (if_then_else
1171 (leu (match_operand:SI 0 "s_register_operand")
1172 (match_operand:SI 1 "arm_rhs_operand"))
1173 (match_dup 4)
1174 (label_ref:SI (match_operand 3 ""))))
1175 (clobber (reg:CC CC_REGNUM))
1176 (clobber (match_scratch:SI 5))
1177 (clobber (match_scratch:SI 6))
1178 (use (label_ref:SI (match_operand 2 "")))])]
1179 "TARGET_THUMB2 && flag_pic"
1180 {
1181 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1182 operands[4] = gen_rtx_PLUS (SImode, operands[4],
1183 gen_rtx_LABEL_REF (SImode, operands[2]));
1184 operands[4] = gen_rtx_MEM (SImode, operands[4]);
1185 MEM_READONLY_P (operands[4]) = 1;
1186 MEM_NOTRAP_P (operands[4]) = 1;
1187 })
1188
1189 (define_insn "*thumb2_casesi_internal_pic"
1190 [(parallel [(set (pc)
1191 (if_then_else
1192 (leu (match_operand:SI 0 "s_register_operand" "r")
1193 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1194 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
1195 (label_ref:SI (match_operand 2 "" ""))))
1196 (label_ref:SI (match_operand 3 "" ""))))
1197 (clobber (reg:CC CC_REGNUM))
1198 (clobber (match_scratch:SI 4 "=&r"))
1199 (clobber (match_scratch:SI 5 "=r"))
1200 (use (label_ref:SI (match_dup 2)))])]
1201 "TARGET_THUMB2 && flag_pic"
1202 "* return thumb2_output_casesi(operands);"
1203 [(set_attr "conds" "clob")
1204 (set_attr "length" "20")
1205 (set_attr "type" "multiple")]
1206 )
1207
1208 (define_insn "*thumb2_return"
1209 [(simple_return)]
1210 "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
1211 "* return output_return_instruction (const_true_rtx, true, false, true);"
1212 [(set_attr "type" "branch")
1213 (set_attr "length" "4")]
1214 )
1215
1216 (define_insn "*thumb2_cmse_entry_return"
1217 [(simple_return)]
1218 "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1219 "* return output_return_instruction (const_true_rtx, true, false, true);"
1220 [(set_attr "type" "branch")
1221 ; This is a return from a cmse_nonsecure_entry function so code will be
1222 ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1223 ; we adapt the length accordingly.
1224 (set (attr "length")
1225 (if_then_else (match_test "TARGET_HARD_FLOAT")
1226 (const_int 34)
1227 (const_int 8)))
1228 ; We do not support predicate execution of returns from cmse_nonsecure_entry
1229 ; functions because we need to clear the APSR. Since predicable has to be
1230 ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1231 ; functions.
1232 (set_attr "predicable" "no")]
1233 )
1234
1235 (define_insn_and_split "thumb2_eh_return"
1236 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1237 VUNSPEC_EH_RETURN)
1238 (clobber (match_scratch:SI 1 "=&r"))]
1239 "TARGET_THUMB2"
1240 "#"
1241 "&& reload_completed"
1242 [(const_int 0)]
1243 "
1244 {
1245 thumb_set_return_address (operands[0], operands[1]);
1246 DONE;
1247 }"
1248 )
1249
1250 (define_insn "*thumb2_alusi3_short"
1251 [(set (match_operand:SI 0 "s_register_operand" "=l")
1252 (match_operator:SI 3 "thumb_16bit_operator"
1253 [(match_operand:SI 1 "s_register_operand" "0")
1254 (match_operand:SI 2 "s_register_operand" "l")]))
1255 (clobber (reg:CC CC_REGNUM))]
1256 "TARGET_THUMB2 && reload_completed
1257 && GET_CODE(operands[3]) != PLUS
1258 && GET_CODE(operands[3]) != MINUS"
1259 "%I3%!\\t%0, %1, %2"
1260 [(set_attr "predicable" "yes")
1261 (set_attr "length" "2")
1262 (set_attr "type" "alu_sreg")]
1263 )
1264
1265 (define_insn "*thumb2_shiftsi3_short"
1266 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1267 (match_operator:SI 3 "shift_operator"
1268 [(match_operand:SI 1 "low_register_operand" "0,l")
1269 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
1270 (clobber (reg:CC CC_REGNUM))]
1271 "TARGET_THUMB2 && reload_completed
1272 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
1273 || REG_P (operands[2]))"
1274 "* return arm_output_shift(operands, 2);"
1275 [(set_attr "predicable" "yes")
1276 (set_attr "shift" "1")
1277 (set_attr "length" "2")
1278 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1279 (if_then_else (match_operand 3 "alu_shift_operator_lsl_1_to_4")
1280 (const_string "alu_shift_imm_lsl_1to4")
1281 (const_string "alu_shift_imm_other"))
1282 (const_string "alu_shift_reg")))]
1283 )
1284
1285 (define_insn "*thumb2_mov<mode>_shortim"
1286 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1287 (match_operand:QHSI 1 "const_int_operand" "I"))
1288 (clobber (reg:CC CC_REGNUM))]
1289 "TARGET_THUMB2 && reload_completed"
1290 "mov%!\t%0, %1"
1291 [(set_attr "predicable" "yes")
1292 (set_attr "length" "2")
1293 (set_attr "type" "mov_imm")]
1294 )
1295
1296 (define_insn "*thumb2_addsi_short"
1297 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1298 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1299 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
1300 (clobber (reg:CC CC_REGNUM))]
1301 "TARGET_THUMB2 && reload_completed"
1302 "*
1303 HOST_WIDE_INT val;
1304
1305 if (CONST_INT_P (operands[2]))
1306 val = INTVAL(operands[2]);
1307 else
1308 val = 0;
1309
1310 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
1311 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1312 return \"sub%!\\t%0, %1, #%n2\";
1313 else
1314 return \"add%!\\t%0, %1, %2\";
1315 "
1316 [(set_attr "predicable" "yes")
1317 (set_attr "length" "2")
1318 (set_attr_alternative "type"
1319 [(if_then_else (match_operand 2 "const_int_operand" "")
1320 (const_string "alu_imm")
1321 (const_string "alu_sreg"))
1322 (const_string "alu_imm")])]
1323 )
1324
1325 (define_insn "*thumb2_subsi_short"
1326 [(set (match_operand:SI 0 "low_register_operand" "=l")
1327 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1328 (match_operand:SI 2 "low_register_operand" "l")))
1329 (clobber (reg:CC CC_REGNUM))]
1330 "TARGET_THUMB2 && reload_completed"
1331 "sub%!\\t%0, %1, %2"
1332 [(set_attr "predicable" "yes")
1333 (set_attr "length" "2")
1334 (set_attr "type" "alu_sreg")]
1335 )
1336
1337 (define_peephole2
1338 [(set (match_operand:CC 0 "cc_register" "")
1339 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1340 (match_operand:SI 2 "const_int_operand" "")))]
1341 "TARGET_THUMB2
1342 && peep2_reg_dead_p (1, operands[1])
1343 && satisfies_constraint_Pw (operands[2])"
1344 [(parallel
1345 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1346 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1347 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1348 )
1349
1350 (define_peephole2
1351 [(match_scratch:SI 3 "l")
1352 (set (match_operand:CC 0 "cc_register" "")
1353 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1354 (match_operand:SI 2 "const_int_operand" "")))]
1355 "TARGET_THUMB2
1356 && satisfies_constraint_Px (operands[2])"
1357 [(parallel
1358 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1359 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1360 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1361 )
1362
1363 (define_insn "thumb2_addsi3_compare0"
1364 [(set (reg:CC_NZ CC_REGNUM)
1365 (compare:CC_NZ
1366 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1367 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1368 (const_int 0)))
1369 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1370 (plus:SI (match_dup 1) (match_dup 2)))]
1371 "TARGET_THUMB2"
1372 "*
1373 HOST_WIDE_INT val;
1374
1375 if (CONST_INT_P (operands[2]))
1376 val = INTVAL (operands[2]);
1377 else
1378 val = 0;
1379
1380 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1381 return \"subs\\t%0, %1, #%n2\";
1382 else
1383 return \"adds\\t%0, %1, %2\";
1384 "
1385 [(set_attr "conds" "set")
1386 (set_attr "length" "2,2,4")
1387 (set_attr_alternative "type"
1388 [(if_then_else (match_operand 2 "const_int_operand" "")
1389 (const_string "alus_imm")
1390 (const_string "alus_sreg"))
1391 (const_string "alus_imm")
1392 (if_then_else (match_operand 2 "const_int_operand" "")
1393 (const_string "alus_imm")
1394 (const_string "alus_sreg"))])]
1395 )
1396
1397 (define_insn "*thumb2_addsi3_compare0_scratch"
1398 [(set (reg:CC_NZ CC_REGNUM)
1399 (compare:CC_NZ
1400 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r")
1401 (match_operand:SI 1 "arm_add_operand" "lPv,rIL"))
1402 (const_int 0)))]
1403 "TARGET_THUMB2"
1404 "*
1405 HOST_WIDE_INT val;
1406
1407 if (CONST_INT_P (operands[1]))
1408 val = INTVAL (operands[1]);
1409 else
1410 val = 0;
1411
1412 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1413 return \"cmp\\t%0, #%n1\";
1414 else
1415 return \"cmn\\t%0, %1\";
1416 "
1417 [(set_attr "conds" "set")
1418 (set_attr "length" "2,4")
1419 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
1420 (const_string "alus_imm")
1421 (const_string "alus_sreg")))]
1422 )
1423
1424 (define_insn "*thumb2_mulsi_short"
1425 [(set (match_operand:SI 0 "low_register_operand" "=l")
1426 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1427 (match_operand:SI 2 "low_register_operand" "l")))
1428 (clobber (reg:CC CC_REGNUM))]
1429 "TARGET_THUMB2 && optimize_size && reload_completed"
1430 "mul%!\\t%0, %2, %0"
1431 [(set_attr "predicable" "yes")
1432 (set_attr "length" "2")
1433 (set_attr "type" "muls")])
1434
1435 (define_insn "*thumb2_mulsi_short_compare0"
1436 [(set (reg:CC_NZ CC_REGNUM)
1437 (compare:CC_NZ
1438 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1439 (match_operand:SI 2 "register_operand" "l"))
1440 (const_int 0)))
1441 (set (match_operand:SI 0 "register_operand" "=l")
1442 (mult:SI (match_dup 1) (match_dup 2)))]
1443 "TARGET_THUMB2 && optimize_size"
1444 "muls\\t%0, %2, %0"
1445 [(set_attr "length" "2")
1446 (set_attr "type" "muls")])
1447
1448 (define_insn "*thumb2_mulsi_short_compare0_scratch"
1449 [(set (reg:CC_NZ CC_REGNUM)
1450 (compare:CC_NZ
1451 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1452 (match_operand:SI 2 "register_operand" "l"))
1453 (const_int 0)))
1454 (clobber (match_scratch:SI 0 "=l"))]
1455 "TARGET_THUMB2 && optimize_size"
1456 "muls\\t%0, %2, %0"
1457 [(set_attr "length" "2")
1458 (set_attr "type" "muls")])
1459
1460 (define_insn "*thumb2_cbz"
1461 [(set (pc) (if_then_else
1462 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1463 (const_int 0))
1464 (label_ref (match_operand 1 "" ""))
1465 (pc)))
1466 (clobber (reg:CC CC_REGNUM))]
1467 "TARGET_THUMB2"
1468 "*
1469 if (get_attr_length (insn) == 2)
1470 return \"cbz\\t%0, %l1\";
1471 else
1472 return \"cmp\\t%0, #0\;beq\\t%l1\";
1473 "
1474 [(set (attr "length")
1475 (if_then_else
1476 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1477 (le (minus (match_dup 1) (pc)) (const_int 128))
1478 (not (match_test "which_alternative")))
1479 (const_int 2)
1480 (const_int 8)))
1481 (set_attr "type" "branch,multiple")]
1482 )
1483
1484 (define_insn "*thumb2_cbnz"
1485 [(set (pc) (if_then_else
1486 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1487 (const_int 0))
1488 (label_ref (match_operand 1 "" ""))
1489 (pc)))
1490 (clobber (reg:CC CC_REGNUM))]
1491 "TARGET_THUMB2"
1492 "*
1493 if (get_attr_length (insn) == 2)
1494 return \"cbnz\\t%0, %l1\";
1495 else
1496 return \"cmp\\t%0, #0\;bne\\t%l1\";
1497 "
1498 [(set (attr "length")
1499 (if_then_else
1500 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
1501 (le (minus (match_dup 1) (pc)) (const_int 128))
1502 (not (match_test "which_alternative")))
1503 (const_int 2)
1504 (const_int 8)))
1505 (set_attr "type" "branch,multiple")]
1506 )
1507
1508 (define_insn "*thumb2_one_cmplsi2_short"
1509 [(set (match_operand:SI 0 "low_register_operand" "=l")
1510 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1511 (clobber (reg:CC CC_REGNUM))]
1512 "TARGET_THUMB2 && reload_completed"
1513 "mvn%!\t%0, %1"
1514 [(set_attr "predicable" "yes")
1515 (set_attr "length" "2")
1516 (set_attr "type" "mvn_reg")]
1517 )
1518
1519 (define_insn "*thumb2_negsi2_short"
1520 [(set (match_operand:SI 0 "low_register_operand" "=l")
1521 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1522 (clobber (reg:CC CC_REGNUM))]
1523 "TARGET_THUMB2 && reload_completed"
1524 "rsb%!\t%0, %1, #0"
1525 [(set_attr "predicable" "yes")
1526 (set_attr "length" "2")
1527 (set_attr "type" "alu_sreg")]
1528 )
1529
1530 (define_insn "*orsi_notsi_si"
1531 [(set (match_operand:SI 0 "s_register_operand" "=r")
1532 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1533 (match_operand:SI 1 "s_register_operand" "r")))]
1534 "TARGET_THUMB2"
1535 "orn%?\\t%0, %1, %2"
1536 [(set_attr "predicable" "yes")
1537 (set_attr "type" "logic_reg")]
1538 )
1539
1540 (define_insn "*orsi_not_shiftsi_si"
1541 [(set (match_operand:SI 0 "s_register_operand" "=r")
1542 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1543 [(match_operand:SI 2 "s_register_operand" "r")
1544 (match_operand:SI 3 "const_int_operand" "M")]))
1545 (match_operand:SI 1 "s_register_operand" "r")))]
1546 "TARGET_THUMB2"
1547 "orn%?\\t%0, %1, %2%S4"
1548 [(set_attr "predicable" "yes")
1549 (set_attr "shift" "2")
1550 (set_attr "autodetect_type" "alu_shift_operator4")]
1551 )
1552
1553 (define_peephole2
1554 [(set (match_operand:CC_NZ 0 "cc_register" "")
1555 (compare:CC_NZ (zero_extract:SI
1556 (match_operand:SI 1 "low_register_operand" "")
1557 (const_int 1)
1558 (match_operand:SI 2 "const_int_operand" ""))
1559 (const_int 0)))
1560 (match_scratch:SI 3 "l")
1561 (set (pc)
1562 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1563 [(match_dup 0) (const_int 0)])
1564 (match_operand 5 "" "")
1565 (match_operand 6 "" "")))]
1566 "TARGET_THUMB2
1567 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1568 && peep2_reg_dead_p (2, operands[0])"
1569 [(parallel [(set (match_dup 0)
1570 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1571 (const_int 0)))
1572 (clobber (match_dup 3))])
1573 (set (pc)
1574 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1575 (match_dup 5) (match_dup 6)))]
1576 "
1577 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1578 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1579 VOIDmode, operands[0], const0_rtx);
1580 ")
1581
1582 (define_peephole2
1583 [(set (match_operand:CC_NZ 0 "cc_register" "")
1584 (compare:CC_NZ (zero_extract:SI
1585 (match_operand:SI 1 "low_register_operand" "")
1586 (match_operand:SI 2 "const_int_operand" "")
1587 (const_int 0))
1588 (const_int 0)))
1589 (match_scratch:SI 3 "l")
1590 (set (pc)
1591 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
1592 [(match_dup 0) (const_int 0)])
1593 (match_operand 5 "" "")
1594 (match_operand 6 "" "")))]
1595 "TARGET_THUMB2
1596 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1597 && peep2_reg_dead_p (2, operands[0])"
1598 [(parallel [(set (match_dup 0)
1599 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1600 (const_int 0)))
1601 (clobber (match_dup 3))])
1602 (set (pc)
1603 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1604 (match_dup 5) (match_dup 6)))]
1605 "
1606 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1607 ")
1608
1609 ;; Define the subtract-one-and-jump insns so loop.c
1610 ;; knows what to generate.
1611 (define_expand "doloop_end"
1612 [(use (match_operand 0 "" "")) ; loop pseudo
1613 (use (match_operand 1 "" ""))] ; label
1614 "TARGET_32BIT"
1615 "
1616 {
1617 /* Currently SMS relies on the do-loop pattern to recognize loops
1618 where (1) the control part consists of all insns defining and/or
1619 using a certain 'count' register and (2) the loop count can be
1620 adjusted by modifying this register prior to the loop.
1621 ??? The possible introduction of a new block to initialize the
1622 new IV can potentially affect branch optimizations.
1623
1624 Also used to implement the low over head loops feature, which is part of
1625 the Armv8.1-M Mainline Low Overhead Branch (LOB) extension. */
1626 if (optimize > 0 && (flag_modulo_sched || TARGET_HAVE_LOB))
1627 {
1628 rtx s0;
1629 rtx bcomp;
1630 rtx loc_ref;
1631 rtx cc_reg;
1632 rtx insn;
1633 rtx cmp;
1634
1635 if (GET_MODE (operands[0]) != SImode)
1636 FAIL;
1637
1638 s0 = operands [0];
1639
1640 /* Low over head loop instructions require the first operand to be LR. */
1641 if (TARGET_HAVE_LOB && arm_target_insn_ok_for_lob (operands [1]))
1642 s0 = gen_rtx_REG (SImode, LR_REGNUM);
1643
1644 if (TARGET_THUMB2)
1645 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1646 else
1647 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1648
1649 cmp = XVECEXP (PATTERN (insn), 0, 0);
1650 cc_reg = SET_DEST (cmp);
1651 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1652 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
1653 emit_jump_insn (gen_rtx_SET (pc_rtx,
1654 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1655 loc_ref, pc_rtx)));
1656 DONE;
1657 }
1658 else
1659 FAIL;
1660 }")
1661
1662 (define_insn "*clear_apsr"
1663 [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1664 (clobber (reg:CC CC_REGNUM))]
1665 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1666 "clrm%?\\t{APSR}"
1667 [(set_attr "predicable" "yes")]
1668 )
1669
1670 ;; The operands are validated through the clear_multiple_operation
1671 ;; match_parallel predicate rather than through constraints so enable it only
1672 ;; after reload.
1673 (define_insn "*clear_multiple"
1674 [(match_parallel 0 "clear_multiple_operation"
1675 [(set (match_operand:SI 1 "register_operand" "")
1676 (const_int 0))])]
1677 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1678 {
1679 char pattern[100];
1680 int i, num_saves = XVECLEN (operands[0], 0);
1681
1682 strcpy (pattern, \"clrm%?\\t{\");
1683 for (i = 0; i < num_saves; i++)
1684 {
1685 if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1686 {
1687 strcat (pattern, \"APSR\");
1688 ++i;
1689 }
1690 else
1691 strcat (pattern,
1692 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1693 if (i < num_saves - 1)
1694 strcat (pattern, \", %|\");
1695 }
1696 strcat (pattern, \"}\");
1697 output_asm_insn (pattern, operands);
1698 return \"\";
1699 }
1700 [(set_attr "predicable" "yes")]
1701 )
1702
1703 (define_insn "thumb2_asrl"
1704 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1705 (ashiftrt:DI (match_dup 0)
1706 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1707 "TARGET_HAVE_MVE"
1708 "asrl%?\\t%Q0, %R0, %1"
1709 [(set_attr "predicable" "yes")])
1710
1711 (define_insn "thumb2_lsll"
1712 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1713 (ashift:DI (match_dup 0)
1714 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
1715 "TARGET_HAVE_MVE"
1716 "lsll%?\\t%Q0, %R0, %1"
1717 [(set_attr "predicable" "yes")])
1718
1719 (define_insn "thumb2_lsrl"
1720 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1721 (lshiftrt:DI (match_dup 0)
1722 (match_operand:SI 1 "long_shift_imm" "Pg")))]
1723 "TARGET_HAVE_MVE"
1724 "lsrl%?\\t%Q0, %R0, %1"
1725 [(set_attr "predicable" "yes")])
1726
1727 ;; Originally expanded by 'doloop_end'.
1728 (define_insn "*doloop_end_internal"
1729 [(set (pc)
1730 (if_then_else
1731 (ne (reg:SI LR_REGNUM) (const_int 1))
1732 (label_ref (match_operand 0 "" ""))
1733 (pc)))
1734 (set (reg:SI LR_REGNUM)
1735 (plus:SI (reg:SI LR_REGNUM) (const_int -1)))
1736 (clobber (reg:CC CC_REGNUM))]
1737 "TARGET_32BIT && TARGET_HAVE_LOB"
1738 {
1739 if (get_attr_length (insn) == 4)
1740 return "le\t%|lr, %l0";
1741 else
1742 return "subs\t%|lr, #1;bne\t%l0";
1743 }
1744 [(set (attr "length")
1745 (if_then_else
1746 (ltu (minus (pc) (match_dup 0)) (const_int 1024))
1747 (const_int 4)
1748 (const_int 6)))
1749 (set_attr "type" "branch")])
1750
1751 (define_expand "doloop_begin"
1752 [(match_operand 0 "" "")
1753 (match_operand 1 "" "")]
1754 "TARGET_32BIT && TARGET_HAVE_LOB"
1755 {
1756 if (REGNO (operands[0]) == LR_REGNUM)
1757 {
1758 emit_insn (gen_dls_insn (operands[0]));
1759 DONE;
1760 }
1761 else
1762 FAIL;
1763 })
1764
1765 (define_insn "dls_insn"
1766 [(set (reg:SI LR_REGNUM)
1767 (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))]
1768 "TARGET_32BIT && TARGET_HAVE_LOB"
1769 "dls\t%|lr, %0")