]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/thumb2.md
arm: Implement Armv8.1-M low overhead loops
[thirdparty/gcc.git] / gcc / config / arm / thumb2.md
CommitLineData
5b3e6663 1;; ARM Thumb-2 Machine Description
8d9254fc 2;; Copyright (C) 2007-2020 Free Software Foundation, Inc.
5b3e6663
PB
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
2f83c7d6 9;; the Free Software Foundation; either version 3, or (at your option)
5b3e6663
PB
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
2f83c7d6
NC
18;; along with GCC; see the file COPYING3. If not see
19;; <http://www.gnu.org/licenses/>. */
5b3e6663
PB
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
95b97fac
KT
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.
0a7dbb76 29(define_insn_and_split "*thumb2_smaxsi3"
95b97fac
KT
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")))
5b3e6663 33 (clobber (reg:CC CC_REGNUM))]
95b97fac
KT
34 "TARGET_THUMB2"
35 "#"
36 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
37 "TARGET_THUMB2 && reload_completed"
0a7dbb76
GY
38 [(set (reg:CC CC_REGNUM)
39 (compare:CC (match_dup 1) (match_dup 2)))
95b97fac
KT
40 (cond_exec (lt:SI (reg:CC CC_REGNUM) (const_int 0))
41 (set (match_dup 0)
42 (match_dup 2)))]
0a7dbb76 43 ""
5b3e6663 44 [(set_attr "conds" "clob")
113c53c3 45 (set_attr "enabled_for_short_it" "yes,yes,no")
594726e4
JG
46 (set_attr "length" "6,6,10")
47 (set_attr "type" "multiple")]
5b3e6663
PB
48)
49
0a7dbb76 50(define_insn_and_split "*thumb2_sminsi3"
95b97fac
KT
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")))
5b3e6663
PB
54 (clobber (reg:CC CC_REGNUM))]
55 "TARGET_THUMB2"
0a7dbb76 56 "#"
95b97fac
KT
57 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
58 "TARGET_THUMB2 && reload_completed"
0a7dbb76
GY
59 [(set (reg:CC CC_REGNUM)
60 (compare:CC (match_dup 1) (match_dup 2)))
95b97fac
KT
61 (cond_exec (ge:SI (reg:CC CC_REGNUM) (const_int 0))
62 (set (match_dup 0)
63 (match_dup 2)))]
0a7dbb76 64 ""
5b3e6663 65 [(set_attr "conds" "clob")
113c53c3 66 (set_attr "enabled_for_short_it" "yes,yes,no")
594726e4
JG
67 (set_attr "length" "6,6,10")
68 (set_attr "type" "multiple")]
5b3e6663
PB
69)
70
0a7dbb76 71(define_insn_and_split "*thumb32_umaxsi3"
95b97fac
KT
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))]
5b3e6663 76 "TARGET_THUMB2"
0a7dbb76 77 "#"
95b97fac
KT
78 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
79 "TARGET_THUMB2 && reload_completed"
0a7dbb76
GY
80 [(set (reg:CC CC_REGNUM)
81 (compare:CC (match_dup 1) (match_dup 2)))
95b97fac
KT
82 (cond_exec (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
83 (set (match_dup 0)
84 (match_dup 2)))]
0a7dbb76 85 ""
5b3e6663 86 [(set_attr "conds" "clob")
95b97fac 87 (set_attr "length" "6,6,10")
113c53c3 88 (set_attr "enabled_for_short_it" "yes,yes,no")
594726e4 89 (set_attr "type" "multiple")]
5b3e6663
PB
90)
91
0a7dbb76 92(define_insn_and_split "*thumb2_uminsi3"
95b97fac
KT
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")))
5b3e6663
PB
96 (clobber (reg:CC CC_REGNUM))]
97 "TARGET_THUMB2"
0a7dbb76 98 "#"
95b97fac
KT
99 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
100 "TARGET_THUMB2 && reload_completed"
0a7dbb76
GY
101 [(set (reg:CC CC_REGNUM)
102 (compare:CC (match_dup 1) (match_dup 2)))
95b97fac
KT
103 (cond_exec (geu:SI (reg:CC CC_REGNUM) (const_int 0))
104 (set (match_dup 0)
105 (match_dup 2)))]
0a7dbb76 106 ""
5b3e6663 107 [(set_attr "conds" "clob")
95b97fac 108 (set_attr "length" "6,6,10")
113c53c3 109 (set_attr "enabled_for_short_it" "yes,yes,no")
594726e4 110 (set_attr "type" "multiple")]
5b3e6663
PB
111)
112
0a7dbb76 113(define_insn_and_split "*thumb2_abssi2"
95b97fac
KT
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")))
5b3e6663
PB
116 (clobber (reg:CC CC_REGNUM))]
117 "TARGET_THUMB2"
0a7dbb76 118 "#"
0a7dbb76 119 ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
95b97fac
KT
120 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
121 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
0a7dbb76
GY
122 "&& reload_completed"
123 [(const_int 0)]
124 {
0a7dbb76
GY
125 if (REGNO(operands[0]) == REGNO(operands[1]))
126 {
127 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
128
f7df4a84
RS
129 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
130 const0_rtx)));
0a7dbb76
GY
131 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
132 (gen_rtx_LT (SImode,
133 cc_reg,
134 const0_rtx)),
f7df4a84 135 (gen_rtx_SET (operands[0],
0a7dbb76
GY
136 (gen_rtx_MINUS (SImode,
137 const0_rtx,
138 operands[1]))))));
139 }
140 else
141 {
f7df4a84 142 emit_insn (gen_rtx_SET (operands[0],
0a7dbb76
GY
143 gen_rtx_XOR (SImode,
144 gen_rtx_ASHIFTRT (SImode,
145 operands[1],
146 GEN_INT (31)),
147 operands[1])));
f7df4a84 148 emit_insn (gen_rtx_SET (operands[0],
0a7dbb76
GY
149 gen_rtx_MINUS (SImode,
150 operands[0],
151 gen_rtx_ASHIFTRT (SImode,
152 operands[1],
153 GEN_INT (31)))));
154 }
155 DONE;
156 }
95b97fac 157 [(set_attr "conds" "*,clob,clob")
5b3e6663 158 (set_attr "shift" "1")
95b97fac 159 (set_attr "predicable" "yes,no,no")
113c53c3 160 (set_attr "enabled_for_short_it" "yes,yes,no")
9cd9d33b 161 (set_attr "ce_count" "2")
594726e4
JG
162 (set_attr "length" "8,6,10")
163 (set_attr "type" "multiple")]
5b3e6663
PB
164)
165
0a7dbb76 166(define_insn_and_split "*thumb2_neg_abssi2"
95b97fac
KT
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"))))
5b3e6663
PB
169 (clobber (reg:CC CC_REGNUM))]
170 "TARGET_THUMB2"
0a7dbb76 171 "#"
95b97fac
KT
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
0a7dbb76 174 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
0a7dbb76
GY
175 "&& reload_completed"
176 [(const_int 0)]
177 {
0a7dbb76
GY
178 if (REGNO(operands[0]) == REGNO(operands[1]))
179 {
180 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
181
f7df4a84
RS
182 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0],
183 const0_rtx)));
0a7dbb76
GY
184 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
185 (gen_rtx_GT (SImode,
186 cc_reg,
187 const0_rtx)),
f7df4a84 188 (gen_rtx_SET (operands[0],
0a7dbb76
GY
189 (gen_rtx_MINUS (SImode,
190 const0_rtx,
191 operands[1]))))));
192 }
193 else
194 {
f7df4a84 195 emit_insn (gen_rtx_SET (operands[0],
0a7dbb76
GY
196 gen_rtx_XOR (SImode,
197 gen_rtx_ASHIFTRT (SImode,
198 operands[1],
199 GEN_INT (31)),
200 operands[1])));
f7df4a84 201 emit_insn (gen_rtx_SET (operands[0],
0a7dbb76
GY
202 gen_rtx_MINUS (SImode,
203 gen_rtx_ASHIFTRT (SImode,
204 operands[1],
205 GEN_INT (31)),
206 operands[0])));
207 }
208 DONE;
209 }
95b97fac 210 [(set_attr "conds" "*,clob,clob")
5b3e6663 211 (set_attr "shift" "1")
95b97fac 212 (set_attr "predicable" "yes,no,no")
113c53c3 213 (set_attr "enabled_for_short_it" "yes,yes,no")
9cd9d33b 214 (set_attr "ce_count" "2")
594726e4
JG
215 (set_attr "length" "8,6,10")
216 (set_attr "type" "multiple")]
5b3e6663
PB
217)
218
f7d2b513
JY
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}"
89b2133e 225 [(set_attr "type" "load_4")
f7d2b513
JY
226 (set_attr "length" "2")
227 (set_attr "predicable" "yes")]
228)
229
28907f9a
MS
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.
5b3e6663 235(define_insn "*thumb2_movsi_insn"
75088696
WD
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"))]
00ea1506 238 "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
5b3e6663
PB
239 && ( register_operand (operands[0], SImode)
240 || register_operand (operands[1], SImode))"
8d33eae8
TP
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:
8d33eae8
TP
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\";
75088696 255 case 6: return \"str%?\\t%1, %0\";
8d33eae8
TP
256 default: gcc_unreachable ();
257 }
258}
75088696
WD
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")
5b3e6663 261 (set_attr "predicable" "yes")
75088696 262 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no")
cefbac6e 263 (set_attr "pool_range" "*,*,*,*,*,1018,*")
75088696 264 (set_attr "neg_pool_range" "*,*,*,*,*,0,*")]
5b3e6663
PB
265)
266
87d05b44 267(define_insn "tls_load_dot_plus_four"
2e5505a4
RE
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")
87d05b44 270 (const_int 4)
2e5505a4
RE
271 (match_operand 3 "" "")]
272 UNSPEC_PIC_BASE)))
273 (clobber (match_scratch:SI 1 "=X,l,X,r"))]
5b3e6663
PB
274 "TARGET_THUMB2"
275 "*
5b3e6663 276 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
2e5505a4
RE
277 INTVAL (operands[3]));
278 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\";
5b3e6663 279 "
594726e4
JG
280 [(set_attr "length" "4,4,6,6")
281 (set_attr "type" "multiple")]
5b3e6663
PB
282)
283
284;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot
44c7bd63 285;; of the messiness associated with the ARM patterns.
5b3e6663 286(define_insn "*thumb2_movhi_insn"
7cb14cb8 287 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,l,r,m,r")
0a2938ae 288 (match_operand:HI 1 "general_operand" "rk,I,Py,n,r,m"))]
c2954af9
RR
289 "TARGET_THUMB2
290 && (register_operand (operands[0], HImode)
291 || register_operand (operands[1], HImode))"
5b3e6663 292 "@
7cb14cb8
KT
293 mov%?\\t%0, %1\\t%@ movhi
294 mov%?\\t%0, %1\\t%@ movhi
5b3e6663
PB
295 mov%?\\t%0, %1\\t%@ movhi
296 movw%?\\t%0, %L1\\t%@ movhi
bae4ce0f
RR
297 strh%?\\t%1, %0\\t%@ movhi
298 ldrh%?\\t%0, %1\\t%@ movhi"
89b2133e 299 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store_4,load_4")
5b3e6663 300 (set_attr "predicable" "yes")
7cb14cb8
KT
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")]
5b3e6663
PB
305)
306
5a200acb
RE
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]!"
89b2133e 319 [(set_attr "type" "store_8")]
5a200acb
RE
320)
321
0a7dbb76 322(define_insn_and_split "*thumb2_mov_scc"
95b97fac 323 [(set (match_operand:SI 0 "s_register_operand" "=l,r")
ac4bf407 324 (match_operator:SI 1 "arm_comparison_operator_mode"
5b3e6663
PB
325 [(match_operand 2 "cc_register" "") (const_int 0)]))]
326 "TARGET_THUMB2"
0a7dbb76
GY
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 ""
5b3e6663 334 [(set_attr "conds" "use")
113c53c3 335 (set_attr "enabled_for_short_it" "yes,no")
594726e4
JG
336 (set_attr "length" "8,10")
337 (set_attr "type" "multiple")]
5b3e6663
PB
338)
339
0a7dbb76 340(define_insn_and_split "*thumb2_mov_negscc"
5b3e6663 341 [(set (match_operand:SI 0 "s_register_operand" "=r")
ac4bf407 342 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
5b3e6663 343 [(match_operand 2 "cc_register" "") (const_int 0)])))]
f6ff841b
RE
344 "TARGET_THUMB2
345 && !arm_restrict_it
346 && !arm_borrow_operation (operands[1], SImode)"
0a7dbb76 347 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
86f697aa 348 "&& true"
0a7dbb76
GY
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 }
5b3e6663 356 [(set_attr "conds" "use")
594726e4
JG
357 (set_attr "length" "10")
358 (set_attr "type" "multiple")]
5b3e6663
PB
359)
360
95b97fac
KT
361(define_insn_and_split "*thumb2_mov_negscc_strict_it"
362 [(set (match_operand:SI 0 "low_register_operand" "=l")
ac4bf407 363 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
95b97fac 364 [(match_operand 2 "cc_register" "") (const_int 0)])))]
f6ff841b
RE
365 "TARGET_THUMB2
366 && arm_restrict_it
367 && !arm_borrow_operation (operands[1], SImode)"
95b97fac
KT
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);
ef4bddc2 377 machine_mode mode = GET_MODE (operands[2]);
95b97fac
KT
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")
594726e4
JG
388 (set_attr "length" "8")
389 (set_attr "type" "multiple")]
95b97fac
KT
390)
391
0a7dbb76 392(define_insn_and_split "*thumb2_mov_notscc"
5b3e6663 393 [(set (match_operand:SI 0 "s_register_operand" "=r")
ac4bf407 394 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
5b3e6663 395 [(match_operand 2 "cc_register" "") (const_int 0)])))]
95b97fac 396 "TARGET_THUMB2 && !arm_restrict_it"
0a7dbb76 397 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
86f697aa 398 "&& true"
0a7dbb76
GY
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 }
5b3e6663 407 [(set_attr "conds" "use")
594726e4
JG
408 (set_attr "length" "10")
409 (set_attr "type" "multiple")]
5b3e6663
PB
410)
411
95b97fac
KT
412(define_insn_and_split "*thumb2_mov_notscc_strict_it"
413 [(set (match_operand:SI 0 "low_register_operand" "=l")
ac4bf407 414 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode"
95b97fac
KT
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")
594726e4
JG
431 (set_attr "length" "8")
432 (set_attr "type" "multiple")]
95b97fac
KT
433)
434
0a7dbb76 435(define_insn_and_split "*thumb2_movsicc_insn"
544f7fc8 436 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r")
5b3e6663
PB
437 (if_then_else:SI
438 (match_operator 3 "arm_comparison_operator"
439 [(match_operand 4 "cc_register" "") (const_int 0)])
544f7fc8
YR
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")))]
5b3e6663
PB
442 "TARGET_THUMB2"
443 "@
956a95a5
KT
444 it\\t%D3\;mov%D3\\t%0, %2
445 it\\t%d3\;mov%d3\\t%0, %1
5b3e6663
PB
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
0a7dbb76
GY
450 #
451 #
452 #
956a95a5 453 #
544f7fc8 454 #
0a7dbb76 455 #"
956a95a5 456 ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
544f7fc8
YR
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
0a7dbb76
GY
462 "&& reload_completed"
463 [(const_int 0)]
464 {
465 enum rtx_code rev_code;
ef4bddc2 466 machine_mode mode;
0a7dbb76
GY
467 rtx rev_cond;
468
469 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
470 operands[3],
f7df4a84 471 gen_rtx_SET (operands[0], operands[1])));
0a7dbb76
GY
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,
f7df4a84 485 gen_rtx_SET (operands[0], operands[2])));
0a7dbb76
GY
486 DONE;
487 }
544f7fc8 488 [(set_attr "length" "4,4,6,6,6,6,10,8,10,10,10,6")
113c53c3 489 (set_attr "enabled_for_short_it" "yes,yes,no,no,no,no,no,no,no,no,no,yes")
594726e4 490 (set_attr "conds" "use")
544f7fc8
YR
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")])]
5b3e6663
PB
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")))]
c7be0832 520 "TARGET_THUMB2 && TARGET_SOFT_FLOAT && !TARGET_HAVE_MVE"
5b3e6663
PB
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")
594726e4
JG
525 (set_attr "conds" "use")
526 (set_attr "type" "multiple")]
5b3e6663
PB
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
c92e08e3 539(define_insn "*nonsecure_call_reg_thumb2"
a464ffc2 540 [(call (unspec:SI [(mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))]
c92e08e3 541 UNSPEC_NONSECURE_MEM)
a464ffc2
MI
542 (match_operand 1 "" ""))
543 (use (match_operand 2 "" ""))
0a413fbc 544 (clobber (reg:SI LR_REGNUM))]
c92e08e3 545 "TARGET_THUMB2 && use_cmse"
a464ffc2
MI
546 {
547 if (TARGET_HAVE_FPCXT_CMSE)
548 return "blxns\\t%0";
549 else
550 return "bl\\t__gnu_cmse_nonsecure_call";
551 }
c92e08e3
AV
552 [(set_attr "length" "4")
553 (set_attr "type" "call")]
554)
555
5b3e6663
PB
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")]
c92e08e3
AV
565)
566
567(define_insn "*nonsecure_call_value_reg_thumb2"
568 [(set (match_operand 0 "" "")
569 (call
a464ffc2 570 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
c92e08e3 571 UNSPEC_NONSECURE_MEM)
a464ffc2
MI
572 (match_operand 2 "" "")))
573 (use (match_operand 3 "" ""))
0a413fbc 574 (clobber (reg:SI LR_REGNUM))]
c92e08e3 575 "TARGET_THUMB2 && use_cmse"
a464ffc2
MI
576 {
577 if (TARGET_HAVE_FPCXT_CMSE)
578 return "blxns\\t%1";
579 else
580 return "bl\\t__gnu_cmse_nonsecure_call";
581 }
c92e08e3
AV
582 [(set_attr "length" "4")
583 (set_attr "type" "call")]
5b3e6663
PB
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"
594726e4
JG
591 [(set_attr "conds" "clob")
592 (set_attr "type" "branch")]
5b3e6663
PB
593)
594;; Don't define thumb2_load_indirect_jump because we can't guarantee label
9e64a0bf 595;; addresses will have the thumb bit set correctly.
5b3e6663
PB
596
597
0a7dbb76 598(define_insn_and_split "*thumb2_and_scc"
956a95a5 599 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
5b3e6663 600 (and:SI (match_operator:SI 1 "arm_comparison_operator"
0a7dbb76
GY
601 [(match_operand 2 "cc_register" "") (const_int 0)])
602 (match_operand:SI 3 "s_register_operand" "r")))]
5b3e6663 603 "TARGET_THUMB2"
956a95a5 604 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0"
0a7dbb76 605 "&& reload_completed"
956a95a5
KT
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)))]
0a7dbb76 609 {
ef4bddc2 610 machine_mode mode = GET_MODE (operands[2]);
0a7dbb76
GY
611 enum rtx_code rc = GET_CODE (operands[1]);
612
0a7dbb76
GY
613 if (mode == CCFPmode || mode == CCFPEmode)
614 rc = reverse_condition_maybe_unordered (rc);
615 else
616 rc = reverse_condition (rc);
956a95a5 617 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
0a7dbb76 618 }
5b3e6663 619 [(set_attr "conds" "use")
594726e4 620 (set_attr "type" "multiple")
956a95a5
KT
621 (set (attr "length") (if_then_else (match_test "arm_restrict_it")
622 (const_int 8)
623 (const_int 10)))]
5b3e6663
PB
624)
625
0a7dbb76 626(define_insn_and_split "*thumb2_ior_scc"
5b3e6663 627 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
0a7dbb76
GY
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")))]
95b97fac 631 "TARGET_THUMB2 && !arm_restrict_it"
5b3e6663 632 "@
0a7dbb76
GY
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 {
ef4bddc2 642 machine_mode mode = GET_MODE (operands[2]);
0a7dbb76
GY
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 }
5b3e6663 652 [(set_attr "conds" "use")
594726e4
JG
653 (set_attr "length" "6,10")
654 (set_attr "type" "multiple")]
5b3e6663
PB
655)
656
fce661e8
KT
657(define_insn_and_split "*thumb2_ior_scc_strict_it"
658 [(set (match_operand:SI 0 "s_register_operand" "=&r")
95b97fac
KT
659 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
660 [(match_operand 3 "cc_register" "") (const_int 0)])
fce661e8 661 (match_operand:SI 1 "s_register_operand" "r")))]
95b97fac 662 "TARGET_THUMB2 && arm_restrict_it"
fce661e8
KT
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 }
95b97fac 678 [(set_attr "conds" "use")
594726e4
JG
679 (set_attr "length" "8")
680 (set_attr "type" "multiple")]
95b97fac
KT
681)
682
5b3e6663
PB
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:
95b97fac
KT
710 if (arm_restrict_it)
711 output_asm_insn (\"it\\t%D4\", operands);
712 else
713 output_asm_insn (\"ite\\t%D4\", operands);
5b3e6663
PB
714 break;
715 default:
716 abort();
717 }
718 if (which_alternative != 0)
95b97fac
KT
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 }
5b3e6663
PB
724 if (which_alternative != 1)
725 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
726 return \"\";
727 "
728 [(set_attr "conds" "use")
594726e4
JG
729 (set_attr "length" "6,6,10")
730 (set_attr "type" "multiple")]
5b3e6663
PB
731)
732
733(define_insn "*thumb2_cond_arith"
734 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9e64a0bf 735 (match_operator:SI 5 "shiftable_operator"
5b3e6663
PB
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))]
95b97fac 741 "TARGET_THUMB2 && !arm_restrict_it"
5b3e6663
PB
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 if (GET_CODE (operands[5]) == AND)
748 {
749 output_asm_insn (\"ite\\t%D4\", operands);
750 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
751 }
752 else if (GET_CODE (operands[5]) == MINUS)
753 {
754 output_asm_insn (\"ite\\t%D4\", operands);
755 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
756 }
757 else if (which_alternative != 0)
758 {
759 output_asm_insn (\"ite\\t%D4\", operands);
760 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
761 }
762 else
763 output_asm_insn (\"it\\t%d4\", operands);
764 return \"%i5%d4\\t%0, %1, #1\";
765 "
766 [(set_attr "conds" "clob")
594726e4
JG
767 (set_attr "length" "14")
768 (set_attr "type" "multiple")]
5b3e6663
PB
769)
770
95b97fac
KT
771(define_insn_and_split "*thumb2_cond_arith_strict_it"
772 [(set (match_operand:SI 0 "s_register_operand" "=l")
773 (match_operator:SI 5 "shiftable_operator_strict_it"
774 [(match_operator:SI 4 "arm_comparison_operator"
775 [(match_operand:SI 2 "s_register_operand" "r")
776 (match_operand:SI 3 "arm_rhs_operand" "rI")])
777 (match_operand:SI 1 "s_register_operand" "0")]))
778 (clobber (reg:CC CC_REGNUM))]
779 "TARGET_THUMB2 && arm_restrict_it"
780 "#"
781 "&& reload_completed"
782 [(const_int 0)]
783 {
784 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
785 {
786 /* %i5 %0, %1, %2, lsr #31 */
787 rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
788 rtx op = NULL_RTX;
789
790 switch (GET_CODE (operands[5]))
791 {
792 case AND:
793 op = gen_rtx_AND (SImode, shifted_op, operands[1]);
794 break;
795 case PLUS:
796 op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
797 break;
798 default: gcc_unreachable ();
799 }
f7df4a84 800 emit_insn (gen_rtx_SET (operands[0], op));
95b97fac
KT
801 DONE;
802 }
803
804 /* "cmp %2, %3" */
f7df4a84
RS
805 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
806 gen_rtx_COMPARE (CCmode, operands[2],
807 operands[3])));
95b97fac
KT
808
809 if (GET_CODE (operands[5]) == AND)
810 {
811 /* %i5 %0, %1, #1
812 it%D4
813 mov%D4 %0, #0 */
814 enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
f7df4a84
RS
815 emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1],
816 GEN_INT (1))));
95b97fac
KT
817 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
818 gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
f7df4a84 819 gen_rtx_SET (operands[0], const0_rtx)));
95b97fac
KT
820 DONE;
821 }
822 else
823 {
824 /* it\\t%d4
825 %i5%d4\\t%0, %1, #1 */
826 emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
827 VOIDmode,
828 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
f7df4a84 829 gen_rtx_SET (operands[0],
95b97fac
KT
830 gen_rtx_PLUS (SImode,
831 operands[1],
832 GEN_INT (1)))));
833 DONE;
834 }
835 FAIL;
836 }
837 [(set_attr "conds" "clob")
594726e4
JG
838 (set_attr "length" "12")
839 (set_attr "type" "multiple")]
95b97fac
KT
840)
841
5b3e6663 842(define_insn "*thumb2_cond_sub"
95b97fac
KT
843 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
844 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
5b3e6663
PB
845 (match_operator:SI 4 "arm_comparison_operator"
846 [(match_operand:SI 2 "s_register_operand" "r,r")
847 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
848 (clobber (reg:CC CC_REGNUM))]
849 "TARGET_THUMB2"
850 "*
851 output_asm_insn (\"cmp\\t%2, %3\", operands);
852 if (which_alternative != 0)
853 {
95b97fac
KT
854 if (arm_restrict_it)
855 {
856 output_asm_insn (\"mov\\t%0, %1\", operands);
857 output_asm_insn (\"it\\t%d4\", operands);
858 }
859 else
860 {
861 output_asm_insn (\"ite\\t%D4\", operands);
862 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
863 }
5b3e6663
PB
864 }
865 else
866 output_asm_insn (\"it\\t%d4\", operands);
867 return \"sub%d4\\t%0, %1, #1\";
868 "
869 [(set_attr "conds" "clob")
594726e4
JG
870 (set_attr "length" "10,14")
871 (set_attr "type" "multiple")]
5b3e6663
PB
872)
873
0a7dbb76 874(define_insn_and_split "*thumb2_negscc"
956a95a5 875 [(set (match_operand:SI 0 "s_register_operand" "=Ts")
5b3e6663
PB
876 (neg:SI (match_operator 3 "arm_comparison_operator"
877 [(match_operand:SI 1 "s_register_operand" "r")
878 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
879 (clobber (reg:CC CC_REGNUM))]
880 "TARGET_THUMB2"
0a7dbb76
GY
881 "#"
882 "&& reload_completed"
883 [(const_int 0)]
884 {
885 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
5b3e6663 886
0a7dbb76
GY
887 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
888 {
889 /* Emit asr\\t%0, %1, #31 */
f7df4a84 890 emit_insn (gen_rtx_SET (operands[0],
0a7dbb76
GY
891 gen_rtx_ASHIFTRT (SImode,
892 operands[1],
893 GEN_INT (31))));
894 DONE;
895 }
956a95a5 896 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it)
0a7dbb76
GY
897 {
898 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */
899 if (CONST_INT_P (operands[2]))
900 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
73ba6c71
JJ
901 gen_int_mode (-INTVAL (operands[2]),
902 SImode)));
0a7dbb76
GY
903 else
904 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
905
906 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
907 gen_rtx_NE (SImode,
908 cc_reg,
909 const0_rtx),
f7df4a84 910 gen_rtx_SET (operands[0],
0a7dbb76
GY
911 GEN_INT (~0))));
912 DONE;
913 }
914 else
915 {
956a95a5 916 /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/
0a7dbb76 917 enum rtx_code rc = reverse_condition (GET_CODE (operands[3]));
ef4bddc2 918 machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]);
0a7dbb76
GY
919 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM);
920
f7df4a84
RS
921 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1],
922 operands[2])));
956a95a5 923
f7df4a84 924 emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0)));
956a95a5 925
0a7dbb76
GY
926 emit_insn (gen_rtx_COND_EXEC (VOIDmode,
927 gen_rtx_fmt_ee (rc,
928 VOIDmode,
929 tmp1,
930 const0_rtx),
f7df4a84 931 gen_rtx_SET (operands[0], const0_rtx)));
0a7dbb76
GY
932 DONE;
933 }
934 FAIL;
935 }
5b3e6663 936 [(set_attr "conds" "clob")
594726e4
JG
937 (set_attr "length" "14")
938 (set_attr "type" "multiple")]
5b3e6663
PB
939)
940
941(define_insn "*thumb2_movcond"
95b97fac 942 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
5b3e6663
PB
943 (if_then_else:SI
944 (match_operator 5 "arm_comparison_operator"
945 [(match_operand:SI 3 "s_register_operand" "r,r,r")
946 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
95b97fac
KT
947 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
948 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
5b3e6663
PB
949 (clobber (reg:CC CC_REGNUM))]
950 "TARGET_THUMB2"
951 "*
952 if (GET_CODE (operands[5]) == LT
953 && (operands[4] == const0_rtx))
954 {
d435a4be 955 if (which_alternative != 1 && REG_P (operands[1]))
5b3e6663
PB
956 {
957 if (operands[2] == const0_rtx)
958 return \"and\\t%0, %1, %3, asr #31\";
959 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\";
960 }
d435a4be 961 else if (which_alternative != 0 && REG_P (operands[2]))
5b3e6663
PB
962 {
963 if (operands[1] == const0_rtx)
964 return \"bic\\t%0, %2, %3, asr #31\";
965 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\";
966 }
967 /* The only case that falls through to here is when both ops 1 & 2
968 are constants. */
969 }
970
971 if (GET_CODE (operands[5]) == GE
972 && (operands[4] == const0_rtx))
973 {
d435a4be 974 if (which_alternative != 1 && REG_P (operands[1]))
5b3e6663
PB
975 {
976 if (operands[2] == const0_rtx)
977 return \"bic\\t%0, %1, %3, asr #31\";
978 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\";
979 }
d435a4be 980 else if (which_alternative != 0 && REG_P (operands[2]))
5b3e6663
PB
981 {
982 if (operands[1] == const0_rtx)
983 return \"and\\t%0, %2, %3, asr #31\";
984 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\";
985 }
986 /* The only case that falls through to here is when both ops 1 & 2
987 are constants. */
988 }
d435a4be 989 if (CONST_INT_P (operands[4])
5b3e6663
PB
990 && !const_ok_for_arm (INTVAL (operands[4])))
991 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
992 else
993 output_asm_insn (\"cmp\\t%3, %4\", operands);
994 switch (which_alternative)
995 {
996 case 0:
997 output_asm_insn (\"it\\t%D5\", operands);
998 break;
999 case 1:
1000 output_asm_insn (\"it\\t%d5\", operands);
1001 break;
1002 case 2:
95b97fac
KT
1003 if (arm_restrict_it)
1004 {
1005 output_asm_insn (\"mov\\t%0, %1\", operands);
1006 output_asm_insn (\"it\\t%D5\", operands);
1007 }
1008 else
1009 output_asm_insn (\"ite\\t%d5\", operands);
5b3e6663
PB
1010 break;
1011 default:
1012 abort();
1013 }
95b97fac 1014 if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
5b3e6663
PB
1015 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
1016 if (which_alternative != 1)
1017 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
1018 return \"\";
1019 "
1020 [(set_attr "conds" "clob")
594726e4
JG
1021 (set_attr "length" "10,10,14")
1022 (set_attr "type" "multiple")]
5b3e6663
PB
1023)
1024
1025;; Zero and sign extension instructions.
1026
5b3e6663
PB
1027;; All supported Thumb2 implementations are armv6, so only that case is
1028;; provided.
1029(define_insn "*thumb2_extendqisi_v6"
1030 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1031 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1032 "TARGET_THUMB2 && arm_arch6"
1033 "@
1034 sxtb%?\\t%0, %1
bae4ce0f 1035 ldrsb%?\\t%0, %1"
006bd006 1036 [(set_attr "type" "extend,load_byte")
5b3e6663 1037 (set_attr "predicable" "yes")
88f519b2 1038 (set_attr "pool_range" "*,4094")
5b3e6663
PB
1039 (set_attr "neg_pool_range" "*,250")]
1040)
1041
1042(define_insn "*thumb2_zero_extendhisi2_v6"
1043 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1044 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1045 "TARGET_THUMB2 && arm_arch6"
1046 "@
1047 uxth%?\\t%0, %1
bae4ce0f 1048 ldrh%?\\t%0, %1"
006bd006 1049 [(set_attr "type" "extend,load_byte")
5b3e6663 1050 (set_attr "predicable" "yes")
88f519b2 1051 (set_attr "pool_range" "*,4094")
5b3e6663
PB
1052 (set_attr "neg_pool_range" "*,250")]
1053)
1054
3565ffed 1055(define_insn "thumb2_zero_extendqisi2_v6"
5b3e6663
PB
1056 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1057 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1058 "TARGET_THUMB2 && arm_arch6"
1059 "@
bae4ce0f
RR
1060 uxtb%?\\t%0, %1
1061 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
006bd006 1062 [(set_attr "type" "extend,load_byte")
5b3e6663 1063 (set_attr "predicable" "yes")
88f519b2 1064 (set_attr "pool_range" "*,4094")
5b3e6663
PB
1065 (set_attr "neg_pool_range" "*,250")]
1066)
1067
9a55a2d1
JJ
1068(define_expand "thumb2_casesi_internal"
1069 [(parallel [(set (pc)
1070 (if_then_else
1071 (leu (match_operand:SI 0 "s_register_operand")
1072 (match_operand:SI 1 "arm_rhs_operand"))
1073 (match_dup 4)
1074 (label_ref:SI (match_operand 3 ""))))
1075 (clobber (reg:CC CC_REGNUM))
1076 (clobber (match_scratch:SI 5))
1077 (use (label_ref:SI (match_operand 2 "")))])]
1078 "TARGET_THUMB2 && !flag_pic"
1079{
1080 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1081 operands[4] = gen_rtx_PLUS (SImode, operands[4],
1082 gen_rtx_LABEL_REF (SImode, operands[2]));
1083 operands[4] = gen_rtx_MEM (SImode, operands[4]);
1084 MEM_READONLY_P (operands[4]) = 1;
1085 MEM_NOTRAP_P (operands[4]) = 1;
1086})
1087
1088(define_insn "*thumb2_casesi_internal"
5b3e6663
PB
1089 [(parallel [(set (pc)
1090 (if_then_else
1091 (leu (match_operand:SI 0 "s_register_operand" "r")
1092 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1093 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9a55a2d1
JJ
1094 (label_ref:SI (match_operand 2 "" ""))))
1095 (label_ref:SI (match_operand 3 "" ""))))
5b3e6663 1096 (clobber (reg:CC CC_REGNUM))
f72d3365 1097 (clobber (match_scratch:SI 4 "=&r"))
9a55a2d1 1098 (use (label_ref:SI (match_dup 2)))])]
5b3e6663
PB
1099 "TARGET_THUMB2 && !flag_pic"
1100 "* return thumb2_output_casesi(operands);"
1101 [(set_attr "conds" "clob")
594726e4
JG
1102 (set_attr "length" "16")
1103 (set_attr "type" "multiple")]
5b3e6663
PB
1104)
1105
9a55a2d1
JJ
1106(define_expand "thumb2_casesi_internal_pic"
1107 [(parallel [(set (pc)
1108 (if_then_else
1109 (leu (match_operand:SI 0 "s_register_operand")
1110 (match_operand:SI 1 "arm_rhs_operand"))
1111 (match_dup 4)
1112 (label_ref:SI (match_operand 3 ""))))
1113 (clobber (reg:CC CC_REGNUM))
1114 (clobber (match_scratch:SI 5))
1115 (clobber (match_scratch:SI 6))
1116 (use (label_ref:SI (match_operand 2 "")))])]
1117 "TARGET_THUMB2 && flag_pic"
1118{
1119 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4));
1120 operands[4] = gen_rtx_PLUS (SImode, operands[4],
1121 gen_rtx_LABEL_REF (SImode, operands[2]));
1122 operands[4] = gen_rtx_MEM (SImode, operands[4]);
1123 MEM_READONLY_P (operands[4]) = 1;
1124 MEM_NOTRAP_P (operands[4]) = 1;
1125})
1126
1127(define_insn "*thumb2_casesi_internal_pic"
5b3e6663
PB
1128 [(parallel [(set (pc)
1129 (if_then_else
1130 (leu (match_operand:SI 0 "s_register_operand" "r")
1131 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1132 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
9a55a2d1
JJ
1133 (label_ref:SI (match_operand 2 "" ""))))
1134 (label_ref:SI (match_operand 3 "" ""))))
5b3e6663 1135 (clobber (reg:CC CC_REGNUM))
f72d3365 1136 (clobber (match_scratch:SI 4 "=&r"))
5b3e6663 1137 (clobber (match_scratch:SI 5 "=r"))
9a55a2d1 1138 (use (label_ref:SI (match_dup 2)))])]
5b3e6663
PB
1139 "TARGET_THUMB2 && flag_pic"
1140 "* return thumb2_output_casesi(operands);"
1141 [(set_attr "conds" "clob")
594726e4
JG
1142 (set_attr "length" "20")
1143 (set_attr "type" "multiple")]
5b3e6663
PB
1144)
1145
7c19c715 1146(define_insn "*thumb2_return"
f79b86a4 1147 [(simple_return)]
de954d6a 1148 "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())"
f79b86a4
IB
1149 "* return output_return_instruction (const_true_rtx, true, false, true);"
1150 [(set_attr "type" "branch")
1151 (set_attr "length" "4")]
7c19c715
JB
1152)
1153
de954d6a
AV
1154(define_insn "*thumb2_cmse_entry_return"
1155 [(simple_return)]
1156 "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())"
1157 "* return output_return_instruction (const_true_rtx, true, false, true);"
1158 [(set_attr "type" "branch")
1159 ; This is a return from a cmse_nonsecure_entry function so code will be
1160 ; added to clear the APSR and potentially the FPSCR if VFP is available, so
1161 ; we adapt the length accordingly.
1162 (set (attr "length")
1163 (if_then_else (match_test "TARGET_HARD_FLOAT")
9f28fe39 1164 (const_int 34)
de954d6a
AV
1165 (const_int 8)))
1166 ; We do not support predicate execution of returns from cmse_nonsecure_entry
1167 ; functions because we need to clear the APSR. Since predicable has to be
1168 ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry
1169 ; functions.
1170 (set_attr "predicable" "no")]
1171)
1172
5b3e6663
PB
1173(define_insn_and_split "thumb2_eh_return"
1174 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
1175 VUNSPEC_EH_RETURN)
1176 (clobber (match_scratch:SI 1 "=&r"))]
1177 "TARGET_THUMB2"
1178 "#"
1179 "&& reload_completed"
1180 [(const_int 0)]
1181 "
1182 {
1183 thumb_set_return_address (operands[0], operands[1]);
1184 DONE;
1185 }"
1186)
1187
5b3e6663
PB
1188(define_insn "*thumb2_alusi3_short"
1189 [(set (match_operand:SI 0 "s_register_operand" "=l")
1190 (match_operator:SI 3 "thumb_16bit_operator"
1191 [(match_operand:SI 1 "s_register_operand" "0")
1192 (match_operand:SI 2 "s_register_operand" "l")]))
1193 (clobber (reg:CC CC_REGNUM))]
d1b85efb
PB
1194 "TARGET_THUMB2 && reload_completed
1195 && GET_CODE(operands[3]) != PLUS
1196 && GET_CODE(operands[3]) != MINUS"
5b3e6663
PB
1197 "%I3%!\\t%0, %1, %2"
1198 [(set_attr "predicable" "yes")
594726e4 1199 (set_attr "length" "2")
1d61feeb 1200 (set_attr "type" "alu_sreg")]
5b3e6663
PB
1201)
1202
5b3e6663 1203(define_insn "*thumb2_shiftsi3_short"
23d2a817 1204 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
5b3e6663 1205 (match_operator:SI 3 "shift_operator"
23d2a817
RE
1206 [(match_operand:SI 1 "low_register_operand" "0,l")
1207 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")]))
5b3e6663
PB
1208 (clobber (reg:CC CC_REGNUM))]
1209 "TARGET_THUMB2 && reload_completed
1210 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT)
d435a4be 1211 || REG_P (operands[2]))"
5b3e6663
PB
1212 "* return arm_output_shift(operands, 2);"
1213 [(set_attr "predicable" "yes")
1214 (set_attr "shift" "1")
1215 (set_attr "length" "2")
1216 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6e4150e1
JG
1217 (const_string "alu_shift_imm")
1218 (const_string "alu_shift_reg")))]
5b3e6663
PB
1219)
1220
953a18fb
RE
1221(define_insn "*thumb2_mov<mode>_shortim"
1222 [(set (match_operand:QHSI 0 "low_register_operand" "=l")
1223 (match_operand:QHSI 1 "const_int_operand" "I"))
5b3e6663
PB
1224 (clobber (reg:CC CC_REGNUM))]
1225 "TARGET_THUMB2 && reload_completed"
1226 "mov%!\t%0, %1"
1227 [(set_attr "predicable" "yes")
594726e4
JG
1228 (set_attr "length" "2")
1229 (set_attr "type" "mov_imm")]
5b3e6663
PB
1230)
1231
d1b85efb 1232(define_insn "*thumb2_addsi_short"
85f28bf1
JB
1233 [(set (match_operand:SI 0 "low_register_operand" "=l,l")
1234 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0")
1235 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps")))
5b3e6663
PB
1236 (clobber (reg:CC CC_REGNUM))]
1237 "TARGET_THUMB2 && reload_completed"
1238 "*
1239 HOST_WIDE_INT val;
1240
d435a4be 1241 if (CONST_INT_P (operands[2]))
d1b85efb
PB
1242 val = INTVAL(operands[2]);
1243 else
1244 val = 0;
1245
5b3e6663
PB
1246 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */
1247 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val)))
1248 return \"sub%!\\t%0, %1, #%n2\";
1249 else
1250 return \"add%!\\t%0, %1, %2\";
1251 "
1252 [(set_attr "predicable" "yes")
594726e4 1253 (set_attr "length" "2")
544f7fc8
YR
1254 (set_attr_alternative "type"
1255 [(if_then_else (match_operand 2 "const_int_operand" "")
1256 (const_string "alu_imm")
1257 (const_string "alu_sreg"))
1258 (const_string "alu_imm")])]
5b3e6663
PB
1259)
1260
d1b85efb
PB
1261(define_insn "*thumb2_subsi_short"
1262 [(set (match_operand:SI 0 "low_register_operand" "=l")
1263 (minus:SI (match_operand:SI 1 "low_register_operand" "l")
1264 (match_operand:SI 2 "low_register_operand" "l")))
1265 (clobber (reg:CC CC_REGNUM))]
1266 "TARGET_THUMB2 && reload_completed"
1267 "sub%!\\t%0, %1, %2"
1268 [(set_attr "predicable" "yes")
594726e4 1269 (set_attr "length" "2")
1d61feeb 1270 (set_attr "type" "alu_sreg")]
d1b85efb
PB
1271)
1272
e6bfe8a2
RE
1273(define_peephole2
1274 [(set (match_operand:CC 0 "cc_register" "")
1275 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1276 (match_operand:SI 2 "const_int_operand" "")))]
1277 "TARGET_THUMB2
1278 && peep2_reg_dead_p (1, operands[1])
1279 && satisfies_constraint_Pw (operands[2])"
1280 [(parallel
1281 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1282 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])]
1283 "operands[3] = GEN_INT (- INTVAL (operands[2]));"
1284)
1285
1286(define_peephole2
1287 [(match_scratch:SI 3 "l")
1288 (set (match_operand:CC 0 "cc_register" "")
1289 (compare:CC (match_operand:SI 1 "low_register_operand" "")
1290 (match_operand:SI 2 "const_int_operand" "")))]
1291 "TARGET_THUMB2
1292 && satisfies_constraint_Px (operands[2])"
1293 [(parallel
1294 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2)))
1295 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])]
1296 "operands[4] = GEN_INT (- INTVAL (operands[2]));"
1297)
1298
ce7b3761 1299(define_insn "thumb2_addsi3_compare0"
54138d95
RH
1300 [(set (reg:CC_NZ CC_REGNUM)
1301 (compare:CC_NZ
dcd8b2ee
JB
1302 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r")
1303 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL"))
1304 (const_int 0)))
1305 (set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1306 (plus:SI (match_dup 1) (match_dup 2)))]
1307 "TARGET_THUMB2"
1308 "*
1309 HOST_WIDE_INT val;
1310
d435a4be 1311 if (CONST_INT_P (operands[2]))
dcd8b2ee
JB
1312 val = INTVAL (operands[2]);
1313 else
1314 val = 0;
1315
1316 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1317 return \"subs\\t%0, %1, #%n2\";
1318 else
1319 return \"adds\\t%0, %1, %2\";
1320 "
1321 [(set_attr "conds" "set")
594726e4 1322 (set_attr "length" "2,2,4")
544f7fc8
YR
1323 (set_attr_alternative "type"
1324 [(if_then_else (match_operand 2 "const_int_operand" "")
1325 (const_string "alus_imm")
1326 (const_string "alus_sreg"))
1327 (const_string "alus_imm")
1328 (if_then_else (match_operand 2 "const_int_operand" "")
1329 (const_string "alus_imm")
1330 (const_string "alus_sreg"))])]
dcd8b2ee
JB
1331)
1332
1333(define_insn "*thumb2_addsi3_compare0_scratch"
54138d95
RH
1334 [(set (reg:CC_NZ CC_REGNUM)
1335 (compare:CC_NZ
544f7fc8
YR
1336 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r")
1337 (match_operand:SI 1 "arm_add_operand" "lPv,rIL"))
dcd8b2ee
JB
1338 (const_int 0)))]
1339 "TARGET_THUMB2"
1340 "*
1341 HOST_WIDE_INT val;
1342
d435a4be 1343 if (CONST_INT_P (operands[1]))
dcd8b2ee
JB
1344 val = INTVAL (operands[1]);
1345 else
1346 val = 0;
1347
1348 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val)))
1349 return \"cmp\\t%0, #%n1\";
1350 else
1351 return \"cmn\\t%0, %1\";
1352 "
1353 [(set_attr "conds" "set")
544f7fc8 1354 (set_attr "length" "2,4")
b43482db 1355 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "")
544f7fc8
YR
1356 (const_string "alus_imm")
1357 (const_string "alus_sreg")))]
dcd8b2ee
JB
1358)
1359
7d31a807
MM
1360(define_insn "*thumb2_mulsi_short"
1361 [(set (match_operand:SI 0 "low_register_operand" "=l")
1362 (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
1363 (match_operand:SI 2 "low_register_operand" "l")))
1364 (clobber (reg:CC CC_REGNUM))]
1365 "TARGET_THUMB2 && optimize_size && reload_completed"
1366 "mul%!\\t%0, %2, %0"
1367 [(set_attr "predicable" "yes")
1368 (set_attr "length" "2")
09485a08 1369 (set_attr "type" "muls")])
7d31a807
MM
1370
1371(define_insn "*thumb2_mulsi_short_compare0"
54138d95
RH
1372 [(set (reg:CC_NZ CC_REGNUM)
1373 (compare:CC_NZ
7d31a807
MM
1374 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1375 (match_operand:SI 2 "register_operand" "l"))
1376 (const_int 0)))
1377 (set (match_operand:SI 0 "register_operand" "=l")
1378 (mult:SI (match_dup 1) (match_dup 2)))]
1379 "TARGET_THUMB2 && optimize_size"
1380 "muls\\t%0, %2, %0"
1381 [(set_attr "length" "2")
09485a08 1382 (set_attr "type" "muls")])
7d31a807
MM
1383
1384(define_insn "*thumb2_mulsi_short_compare0_scratch"
54138d95
RH
1385 [(set (reg:CC_NZ CC_REGNUM)
1386 (compare:CC_NZ
7d31a807
MM
1387 (mult:SI (match_operand:SI 1 "register_operand" "%0")
1388 (match_operand:SI 2 "register_operand" "l"))
1389 (const_int 0)))
3fc604fc 1390 (clobber (match_scratch:SI 0 "=l"))]
7d31a807
MM
1391 "TARGET_THUMB2 && optimize_size"
1392 "muls\\t%0, %2, %0"
1393 [(set_attr "length" "2")
09485a08 1394 (set_attr "type" "muls")])
7d31a807 1395
5b3e6663
PB
1396(define_insn "*thumb2_cbz"
1397 [(set (pc) (if_then_else
1398 (eq (match_operand:SI 0 "s_register_operand" "l,?r")
1399 (const_int 0))
1400 (label_ref (match_operand 1 "" ""))
1401 (pc)))
1402 (clobber (reg:CC CC_REGNUM))]
1403 "TARGET_THUMB2"
1404 "*
98ac6510 1405 if (get_attr_length (insn) == 2)
5b3e6663
PB
1406 return \"cbz\\t%0, %l1\";
1407 else
1408 return \"cmp\\t%0, #0\;beq\\t%l1\";
1409 "
9e64a0bf 1410 [(set (attr "length")
5b3e6663
PB
1411 (if_then_else
1412 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
98ac6510 1413 (le (minus (match_dup 1) (pc)) (const_int 128))
b75b1be2 1414 (not (match_test "which_alternative")))
5b3e6663 1415 (const_int 2)
594726e4
JG
1416 (const_int 8)))
1417 (set_attr "type" "branch,multiple")]
5b3e6663
PB
1418)
1419
1420(define_insn "*thumb2_cbnz"
1421 [(set (pc) (if_then_else
1422 (ne (match_operand:SI 0 "s_register_operand" "l,?r")
1423 (const_int 0))
1424 (label_ref (match_operand 1 "" ""))
1425 (pc)))
1426 (clobber (reg:CC CC_REGNUM))]
1427 "TARGET_THUMB2"
1428 "*
98ac6510 1429 if (get_attr_length (insn) == 2)
5b3e6663
PB
1430 return \"cbnz\\t%0, %l1\";
1431 else
1432 return \"cmp\\t%0, #0\;bne\\t%l1\";
1433 "
9e64a0bf 1434 [(set (attr "length")
5b3e6663
PB
1435 (if_then_else
1436 (and (ge (minus (match_dup 1) (pc)) (const_int 2))
98ac6510 1437 (le (minus (match_dup 1) (pc)) (const_int 128))
b75b1be2 1438 (not (match_test "which_alternative")))
5b3e6663 1439 (const_int 2)
594726e4
JG
1440 (const_int 8)))
1441 (set_attr "type" "branch,multiple")]
5b3e6663 1442)
d1b85efb 1443
d1b85efb
PB
1444(define_insn "*thumb2_one_cmplsi2_short"
1445 [(set (match_operand:SI 0 "low_register_operand" "=l")
1446 (not:SI (match_operand:SI 1 "low_register_operand" "l")))
1447 (clobber (reg:CC CC_REGNUM))]
1448 "TARGET_THUMB2 && reload_completed"
1449 "mvn%!\t%0, %1"
1450 [(set_attr "predicable" "yes")
594726e4
JG
1451 (set_attr "length" "2")
1452 (set_attr "type" "mvn_reg")]
d1b85efb
PB
1453)
1454
d1b85efb
PB
1455(define_insn "*thumb2_negsi2_short"
1456 [(set (match_operand:SI 0 "low_register_operand" "=l")
1457 (neg:SI (match_operand:SI 1 "low_register_operand" "l")))
1458 (clobber (reg:CC CC_REGNUM))]
1459 "TARGET_THUMB2 && reload_completed"
4b04107b 1460 "rsb%!\t%0, %1, #0"
d1b85efb 1461 [(set_attr "predicable" "yes")
594726e4 1462 (set_attr "length" "2")
1d61feeb 1463 (set_attr "type" "alu_sreg")]
d1b85efb
PB
1464)
1465
c29e2982 1466(define_insn "*orsi_notsi_si"
a7994a57
RR
1467 [(set (match_operand:SI 0 "s_register_operand" "=r")
1468 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
64af62c2 1469 (match_operand:SI 1 "s_register_operand" "r")))]
a7994a57
RR
1470 "TARGET_THUMB2"
1471 "orn%?\\t%0, %1, %2"
95b97fac 1472 [(set_attr "predicable" "yes")
594726e4 1473 (set_attr "type" "logic_reg")]
a7994a57
RR
1474)
1475
c29e2982 1476(define_insn "*orsi_not_shiftsi_si"
a7994a57
RR
1477 [(set (match_operand:SI 0 "s_register_operand" "=r")
1478 (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
1479 [(match_operand:SI 2 "s_register_operand" "r")
1480 (match_operand:SI 3 "const_int_operand" "M")]))
1481 (match_operand:SI 1 "s_register_operand" "r")))]
1482 "TARGET_THUMB2"
1483 "orn%?\\t%0, %1, %2%S4"
1484 [(set_attr "predicable" "yes")
1485 (set_attr "shift" "2")
6e4150e1 1486 (set_attr "type" "alu_shift_imm")]
a7994a57
RR
1487)
1488
8850383b 1489(define_peephole2
54138d95
RH
1490 [(set (match_operand:CC_NZ 0 "cc_register" "")
1491 (compare:CC_NZ (zero_extract:SI
8850383b
RE
1492 (match_operand:SI 1 "low_register_operand" "")
1493 (const_int 1)
1494 (match_operand:SI 2 "const_int_operand" ""))
1495 (const_int 0)))
1496 (match_scratch:SI 3 "l")
1497 (set (pc)
54138d95 1498 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
8850383b
RE
1499 [(match_dup 0) (const_int 0)])
1500 (match_operand 5 "" "")
1501 (match_operand 6 "" "")))]
1502 "TARGET_THUMB2
bae7adda
KT
1503 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
1504 && peep2_reg_dead_p (2, operands[0])"
8850383b 1505 [(parallel [(set (match_dup 0)
54138d95 1506 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
8850383b
RE
1507 (const_int 0)))
1508 (clobber (match_dup 3))])
1509 (set (pc)
1510 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1511 (match_dup 5) (match_dup 6)))]
1512 "
1513 operands[2] = GEN_INT (31 - INTVAL (operands[2]));
1514 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE,
1515 VOIDmode, operands[0], const0_rtx);
1516 ")
333b67a9 1517
ece53c91 1518(define_peephole2
54138d95
RH
1519 [(set (match_operand:CC_NZ 0 "cc_register" "")
1520 (compare:CC_NZ (zero_extract:SI
ece53c91
WG
1521 (match_operand:SI 1 "low_register_operand" "")
1522 (match_operand:SI 2 "const_int_operand" "")
1523 (const_int 0))
1524 (const_int 0)))
1525 (match_scratch:SI 3 "l")
1526 (set (pc)
54138d95 1527 (if_then_else (match_operator:CC_NZ 4 "equality_operator"
ece53c91
WG
1528 [(match_dup 0) (const_int 0)])
1529 (match_operand 5 "" "")
1530 (match_operand 6 "" "")))]
1531 "TARGET_THUMB2
bae7adda
KT
1532 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32)
1533 && peep2_reg_dead_p (2, operands[0])"
ece53c91 1534 [(parallel [(set (match_dup 0)
54138d95
RH
1535 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2))
1536 (const_int 0)))
ece53c91
WG
1537 (clobber (match_dup 3))])
1538 (set (pc)
1539 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)])
1540 (match_dup 5) (match_dup 6)))]
88c1612f
WG
1541 "
1542 operands[2] = GEN_INT (32 - INTVAL (operands[2]));
ece53c91 1543 ")
ce7b3761
RE
1544
1545;; Define the subtract-one-and-jump insns so loop.c
1546;; knows what to generate.
1547(define_expand "doloop_end"
1548 [(use (match_operand 0 "" "")) ; loop pseudo
1d0216c8 1549 (use (match_operand 1 "" ""))] ; label
ce7b3761
RE
1550 "TARGET_32BIT"
1551 "
1552 {
1553 /* Currently SMS relies on the do-loop pattern to recognize loops
1554 where (1) the control part consists of all insns defining and/or
1555 using a certain 'count' register and (2) the loop count can be
1556 adjusted by modifying this register prior to the loop.
1557 ??? The possible introduction of a new block to initialize the
d2ed233c
AC
1558 new IV can potentially affect branch optimizations.
1559
1560 Also used to implement the low over head loops feature, which is part of
1561 the Armv8.1-M Mainline Low Overhead Branch (LOB) extension. */
1562 if (optimize > 0 && (flag_modulo_sched || TARGET_HAVE_LOB))
ce7b3761
RE
1563 {
1564 rtx s0;
1565 rtx bcomp;
1566 rtx loc_ref;
1567 rtx cc_reg;
1568 rtx insn;
1569 rtx cmp;
1570
ce7b3761
RE
1571 if (GET_MODE (operands[0]) != SImode)
1572 FAIL;
1573
1574 s0 = operands [0];
d2ed233c
AC
1575
1576 /* Low over head loop instructions require the first operand to be LR. */
1577 if (TARGET_HAVE_LOB && arm_target_insn_ok_for_lob (operands [1]))
1578 s0 = gen_rtx_REG (SImode, LR_REGNUM);
1579
ce7b3761
RE
1580 if (TARGET_THUMB2)
1581 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1582 else
1583 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1)));
1584
1585 cmp = XVECEXP (PATTERN (insn), 0, 0);
1586 cc_reg = SET_DEST (cmp);
1587 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
1d0216c8 1588 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
f7df4a84 1589 emit_jump_insn (gen_rtx_SET (pc_rtx,
ce7b3761
RE
1590 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
1591 loc_ref, pc_rtx)));
1592 DONE;
d2ed233c
AC
1593 }
1594 else
1595 FAIL;
ce7b3761
RE
1596 }")
1597
9722215a
MI
1598(define_insn "*clear_apsr"
1599 [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR)
1600 (clobber (reg:CC CC_REGNUM))]
1601 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse"
1602 "clrm%?\\t{APSR}"
1603 [(set_attr "predicable" "yes")]
1604)
1605
1606;; The operands are validated through the clear_multiple_operation
1607;; match_parallel predicate rather than through constraints so enable it only
1608;; after reload.
1609(define_insn "*clear_multiple"
1610 [(match_parallel 0 "clear_multiple_operation"
1611 [(set (match_operand:SI 1 "register_operand" "")
1612 (const_int 0))])]
1613 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed"
1614 {
1615 char pattern[100];
1616 int i, num_saves = XVECLEN (operands[0], 0);
1617
1618 strcpy (pattern, \"clrm%?\\t{\");
1619 for (i = 0; i < num_saves; i++)
1620 {
1621 if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE)
1622 {
1623 strcat (pattern, \"APSR\");
1624 ++i;
1625 }
1626 else
1627 strcat (pattern,
1628 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]);
1629 if (i < num_saves - 1)
1630 strcat (pattern, \", %|\");
1631 }
1632 strcat (pattern, \"}\");
1633 output_asm_insn (pattern, operands);
1634 return \"\";
1635 }
1636 [(set_attr "predicable" "yes")]
1637)
60d616b1
MI
1638
1639(define_insn "thumb2_asrl"
1640 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1641 (ashiftrt:DI (match_dup 0)
a968a40c 1642 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
60d616b1
MI
1643 "TARGET_HAVE_MVE"
1644 "asrl%?\\t%Q0, %R0, %1"
1645 [(set_attr "predicable" "yes")])
1646
1647(define_insn "thumb2_lsll"
1648 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1649 (ashift:DI (match_dup 0)
a968a40c 1650 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))]
60d616b1
MI
1651 "TARGET_HAVE_MVE"
1652 "lsll%?\\t%Q0, %R0, %1"
1653 [(set_attr "predicable" "yes")])
a968a40c
MI
1654
1655(define_insn "thumb2_lsrl"
1656 [(set (match_operand:DI 0 "arm_general_register_operand" "+r")
1657 (lshiftrt:DI (match_dup 0)
1658 (match_operand:SI 1 "long_shift_imm" "Pg")))]
1659 "TARGET_HAVE_MVE"
1660 "lsrl%?\\t%Q0, %R0, %1"
1661 [(set_attr "predicable" "yes")])
d2ed233c
AC
1662
1663;; Originally expanded by 'doloop_end'.
1664(define_insn "*doloop_end_internal"
1665 [(parallel [(set (pc)
1666 (if_then_else
1667 (ne (reg:SI LR_REGNUM) (const_int 1))
1668 (label_ref (match_operand 0 "" ""))
1669 (pc)))
1670 (set (reg:SI LR_REGNUM)
1671 (plus:SI (reg:SI LR_REGNUM) (const_int -1)))])]
1672 "TARGET_32BIT && TARGET_HAVE_LOB"
1673 "le\t%|lr, %l0")
1674
1675(define_expand "doloop_begin"
1676 [(match_operand 0 "" "")
1677 (match_operand 1 "" "")]
1678 "TARGET_32BIT && TARGET_HAVE_LOB"
1679 {
1680 if (REGNO (operands[0]) == LR_REGNUM)
1681 {
1682 emit_insn (gen_dls_insn (operands[0]));
1683 DONE;
1684 }
1685 else
1686 FAIL;
1687 })
1688
1689(define_insn "dls_insn"
1690 [(set (reg:SI LR_REGNUM)
1691 (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))]
1692 "TARGET_32BIT && TARGET_HAVE_LOB"
1693 "dls\t%|lr, %0")