]>
Commit | Line | Data |
---|---|---|
5b3e6663 | 1 | ;; ARM Thumb-2 Machine Description |
aeee4812 | 2 | ;; Copyright (C) 2007-2023 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 | ||
44ab1cc1 | 539 | (define_insn "*nonsecure_call_reg_thumb2_fpcxt" |
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))] |
44ab1cc1 RE |
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" | |
c92e08e3 AV |
559 | [(set_attr "length" "4") |
560 | (set_attr "type" "call")] | |
561 | ) | |
562 | ||
5b3e6663 PB |
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")] | |
c92e08e3 AV |
572 | ) |
573 | ||
44ab1cc1 | 574 | (define_insn "*nonsecure_call_value_reg_thumb2_fpcxt" |
c92e08e3 AV |
575 | [(set (match_operand 0 "" "") |
576 | (call | |
a464ffc2 | 577 | (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))] |
c92e08e3 | 578 | UNSPEC_NONSECURE_MEM) |
a464ffc2 MI |
579 | (match_operand 2 "" ""))) |
580 | (use (match_operand 3 "" "")) | |
0a413fbc | 581 | (clobber (reg:SI LR_REGNUM))] |
44ab1cc1 RE |
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" | |
c92e08e3 AV |
597 | [(set_attr "length" "4") |
598 | (set_attr "type" "call")] | |
5b3e6663 PB |
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" | |
594726e4 JG |
606 | [(set_attr "conds" "clob") |
607 | (set_attr "type" "branch")] | |
5b3e6663 PB |
608 | ) |
609 | ;; Don't define thumb2_load_indirect_jump because we can't guarantee label | |
9e64a0bf | 610 | ;; addresses will have the thumb bit set correctly. |
5b3e6663 PB |
611 | |
612 | ||
0a7dbb76 | 613 | (define_insn_and_split "*thumb2_and_scc" |
956a95a5 | 614 | [(set (match_operand:SI 0 "s_register_operand" "=Ts") |
5b3e6663 | 615 | (and:SI (match_operator:SI 1 "arm_comparison_operator" |
0a7dbb76 GY |
616 | [(match_operand 2 "cc_register" "") (const_int 0)]) |
617 | (match_operand:SI 3 "s_register_operand" "r")))] | |
5b3e6663 | 618 | "TARGET_THUMB2" |
956a95a5 | 619 | "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0" |
0a7dbb76 | 620 | "&& reload_completed" |
956a95a5 KT |
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)))] | |
0a7dbb76 | 624 | { |
ef4bddc2 | 625 | machine_mode mode = GET_MODE (operands[2]); |
0a7dbb76 GY |
626 | enum rtx_code rc = GET_CODE (operands[1]); |
627 | ||
0a7dbb76 GY |
628 | if (mode == CCFPmode || mode == CCFPEmode) |
629 | rc = reverse_condition_maybe_unordered (rc); | |
630 | else | |
631 | rc = reverse_condition (rc); | |
956a95a5 | 632 | operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx); |
0a7dbb76 | 633 | } |
5b3e6663 | 634 | [(set_attr "conds" "use") |
594726e4 | 635 | (set_attr "type" "multiple") |
956a95a5 KT |
636 | (set (attr "length") (if_then_else (match_test "arm_restrict_it") |
637 | (const_int 8) | |
638 | (const_int 10)))] | |
5b3e6663 PB |
639 | ) |
640 | ||
0a7dbb76 | 641 | (define_insn_and_split "*thumb2_ior_scc" |
5b3e6663 | 642 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") |
0a7dbb76 GY |
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")))] | |
95b97fac | 646 | "TARGET_THUMB2 && !arm_restrict_it" |
5b3e6663 | 647 | "@ |
0a7dbb76 GY |
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 | { | |
ef4bddc2 | 657 | machine_mode mode = GET_MODE (operands[2]); |
0a7dbb76 GY |
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 | } | |
5b3e6663 | 667 | [(set_attr "conds" "use") |
594726e4 JG |
668 | (set_attr "length" "6,10") |
669 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
670 | ) |
671 | ||
fce661e8 KT |
672 | (define_insn_and_split "*thumb2_ior_scc_strict_it" |
673 | [(set (match_operand:SI 0 "s_register_operand" "=&r") | |
95b97fac KT |
674 | (ior:SI (match_operator:SI 2 "arm_comparison_operator" |
675 | [(match_operand 3 "cc_register" "") (const_int 0)]) | |
fce661e8 | 676 | (match_operand:SI 1 "s_register_operand" "r")))] |
95b97fac | 677 | "TARGET_THUMB2 && arm_restrict_it" |
fce661e8 KT |
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 | } | |
95b97fac | 693 | [(set_attr "conds" "use") |
594726e4 JG |
694 | (set_attr "length" "8") |
695 | (set_attr "type" "multiple")] | |
95b97fac KT |
696 | ) |
697 | ||
5b3e6663 PB |
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: | |
95b97fac KT |
725 | if (arm_restrict_it) |
726 | output_asm_insn (\"it\\t%D4\", operands); | |
727 | else | |
728 | output_asm_insn (\"ite\\t%D4\", operands); | |
5b3e6663 PB |
729 | break; |
730 | default: | |
731 | abort(); | |
732 | } | |
733 | if (which_alternative != 0) | |
95b97fac KT |
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 | } | |
5b3e6663 PB |
739 | if (which_alternative != 1) |
740 | output_asm_insn (\"mov%d4\\t%0, %2\", operands); | |
741 | return \"\"; | |
742 | " | |
743 | [(set_attr "conds" "use") | |
594726e4 JG |
744 | (set_attr "length" "6,6,10") |
745 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
746 | ) |
747 | ||
748 | (define_insn "*thumb2_cond_arith" | |
749 | [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
9e64a0bf | 750 | (match_operator:SI 5 "shiftable_operator" |
5b3e6663 PB |
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))] | |
95b97fac | 756 | "TARGET_THUMB2 && !arm_restrict_it" |
5b3e6663 PB |
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); | |
778f19ff SD |
762 | |
763 | if (GET_CODE (operands[5]) == PLUS && TARGET_COND_ARITH) | |
764 | return \"cinc\\t%0, %1, %d4\"; | |
765 | ||
5b3e6663 PB |
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") | |
594726e4 JG |
786 | (set_attr "length" "14") |
787 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
788 | ) |
789 | ||
95b97fac KT |
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 | } | |
f7df4a84 | 819 | emit_insn (gen_rtx_SET (operands[0], op)); |
95b97fac KT |
820 | DONE; |
821 | } | |
822 | ||
823 | /* "cmp %2, %3" */ | |
f7df4a84 RS |
824 | emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM), |
825 | gen_rtx_COMPARE (CCmode, operands[2], | |
826 | operands[3]))); | |
95b97fac KT |
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])); | |
f7df4a84 RS |
834 | emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1], |
835 | GEN_INT (1)))); | |
95b97fac KT |
836 | emit_insn (gen_rtx_COND_EXEC (VOIDmode, |
837 | gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx), | |
f7df4a84 | 838 | gen_rtx_SET (operands[0], const0_rtx))); |
95b97fac KT |
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), | |
f7df4a84 | 848 | gen_rtx_SET (operands[0], |
95b97fac KT |
849 | gen_rtx_PLUS (SImode, |
850 | operands[1], | |
851 | GEN_INT (1))))); | |
852 | DONE; | |
853 | } | |
854 | FAIL; | |
855 | } | |
856 | [(set_attr "conds" "clob") | |
594726e4 JG |
857 | (set_attr "length" "12") |
858 | (set_attr "type" "multiple")] | |
95b97fac KT |
859 | ) |
860 | ||
5b3e6663 | 861 | (define_insn "*thumb2_cond_sub" |
95b97fac KT |
862 | [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts") |
863 | (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts") | |
5b3e6663 PB |
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 | { | |
95b97fac KT |
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 | } | |
5b3e6663 PB |
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") | |
594726e4 JG |
889 | (set_attr "length" "10,14") |
890 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
891 | ) |
892 | ||
0a7dbb76 | 893 | (define_insn_and_split "*thumb2_negscc" |
956a95a5 | 894 | [(set (match_operand:SI 0 "s_register_operand" "=Ts") |
5b3e6663 PB |
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))] | |
04dc198c | 899 | "TARGET_THUMB2 && !TARGET_COND_ARITH" |
0a7dbb76 GY |
900 | "#" |
901 | "&& reload_completed" | |
902 | [(const_int 0)] | |
903 | { | |
904 | rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); | |
5b3e6663 | 905 | |
0a7dbb76 GY |
906 | if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx) |
907 | { | |
908 | /* Emit asr\\t%0, %1, #31 */ | |
f7df4a84 | 909 | emit_insn (gen_rtx_SET (operands[0], |
0a7dbb76 GY |
910 | gen_rtx_ASHIFTRT (SImode, |
911 | operands[1], | |
912 | GEN_INT (31)))); | |
913 | DONE; | |
914 | } | |
956a95a5 | 915 | else if (GET_CODE (operands[3]) == NE && !arm_restrict_it) |
0a7dbb76 GY |
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], | |
73ba6c71 JJ |
920 | gen_int_mode (-INTVAL (operands[2]), |
921 | SImode))); | |
0a7dbb76 GY |
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), | |
f7df4a84 | 929 | gen_rtx_SET (operands[0], |
0a7dbb76 GY |
930 | GEN_INT (~0)))); |
931 | DONE; | |
932 | } | |
933 | else | |
934 | { | |
956a95a5 | 935 | /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/ |
0a7dbb76 | 936 | enum rtx_code rc = reverse_condition (GET_CODE (operands[3])); |
ef4bddc2 | 937 | machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]); |
0a7dbb76 GY |
938 | rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM); |
939 | ||
f7df4a84 RS |
940 | emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1], |
941 | operands[2]))); | |
956a95a5 | 942 | |
f7df4a84 | 943 | emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0))); |
956a95a5 | 944 | |
0a7dbb76 GY |
945 | emit_insn (gen_rtx_COND_EXEC (VOIDmode, |
946 | gen_rtx_fmt_ee (rc, | |
947 | VOIDmode, | |
948 | tmp1, | |
949 | const0_rtx), | |
f7df4a84 | 950 | gen_rtx_SET (operands[0], const0_rtx))); |
0a7dbb76 GY |
951 | DONE; |
952 | } | |
953 | FAIL; | |
954 | } | |
5b3e6663 | 955 | [(set_attr "conds" "clob") |
594726e4 JG |
956 | (set_attr "length" "14") |
957 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
958 | ) |
959 | ||
c2bb84be SD |
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")] | |
778f19ff SD |
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")] | |
04dc198c SD |
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")] | |
c2bb84be SD |
1001 | ) |
1002 | ||
5b3e6663 | 1003 | (define_insn "*thumb2_movcond" |
95b97fac | 1004 | [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts") |
5b3e6663 PB |
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")]) | |
95b97fac KT |
1009 | (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI") |
1010 | (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI"))) | |
5b3e6663 | 1011 | (clobber (reg:CC CC_REGNUM))] |
c2bb84be | 1012 | "TARGET_THUMB2 && !TARGET_COND_ARITH" |
5b3e6663 PB |
1013 | "* |
1014 | if (GET_CODE (operands[5]) == LT | |
1015 | && (operands[4] == const0_rtx)) | |
1016 | { | |
d435a4be | 1017 | if (which_alternative != 1 && REG_P (operands[1])) |
5b3e6663 PB |
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 | } | |
d435a4be | 1023 | else if (which_alternative != 0 && REG_P (operands[2])) |
5b3e6663 PB |
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 | { | |
d435a4be | 1036 | if (which_alternative != 1 && REG_P (operands[1])) |
5b3e6663 PB |
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 | } | |
d435a4be | 1042 | else if (which_alternative != 0 && REG_P (operands[2])) |
5b3e6663 PB |
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 | } | |
d435a4be | 1051 | if (CONST_INT_P (operands[4]) |
5b3e6663 PB |
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: | |
95b97fac KT |
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); | |
5b3e6663 PB |
1072 | break; |
1073 | default: | |
1074 | abort(); | |
1075 | } | |
95b97fac | 1076 | if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2)) |
5b3e6663 PB |
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") | |
594726e4 JG |
1083 | (set_attr "length" "10,10,14") |
1084 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
1085 | ) |
1086 | ||
1087 | ;; Zero and sign extension instructions. | |
1088 | ||
5b3e6663 PB |
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 | |
bae4ce0f | 1097 | ldrsb%?\\t%0, %1" |
006bd006 | 1098 | [(set_attr "type" "extend,load_byte") |
5b3e6663 | 1099 | (set_attr "predicable" "yes") |
88f519b2 | 1100 | (set_attr "pool_range" "*,4094") |
5b3e6663 PB |
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 | |
bae4ce0f | 1110 | ldrh%?\\t%0, %1" |
006bd006 | 1111 | [(set_attr "type" "extend,load_byte") |
5b3e6663 | 1112 | (set_attr "predicable" "yes") |
88f519b2 | 1113 | (set_attr "pool_range" "*,4094") |
5b3e6663 PB |
1114 | (set_attr "neg_pool_range" "*,250")] |
1115 | ) | |
1116 | ||
3565ffed | 1117 | (define_insn "thumb2_zero_extendqisi2_v6" |
5b3e6663 PB |
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 | "@ | |
bae4ce0f RR |
1122 | uxtb%?\\t%0, %1 |
1123 | ldrb%?\\t%0, %1\\t%@ zero_extendqisi2" | |
006bd006 | 1124 | [(set_attr "type" "extend,load_byte") |
5b3e6663 | 1125 | (set_attr "predicable" "yes") |
88f519b2 | 1126 | (set_attr "pool_range" "*,4094") |
5b3e6663 PB |
1127 | (set_attr "neg_pool_range" "*,250")] |
1128 | ) | |
1129 | ||
9a55a2d1 JJ |
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" | |
5b3e6663 PB |
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)) | |
9a55a2d1 JJ |
1156 | (label_ref:SI (match_operand 2 "" "")))) |
1157 | (label_ref:SI (match_operand 3 "" "")))) | |
5b3e6663 | 1158 | (clobber (reg:CC CC_REGNUM)) |
f72d3365 | 1159 | (clobber (match_scratch:SI 4 "=&r")) |
9a55a2d1 | 1160 | (use (label_ref:SI (match_dup 2)))])] |
5b3e6663 PB |
1161 | "TARGET_THUMB2 && !flag_pic" |
1162 | "* return thumb2_output_casesi(operands);" | |
1163 | [(set_attr "conds" "clob") | |
594726e4 JG |
1164 | (set_attr "length" "16") |
1165 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
1166 | ) |
1167 | ||
9a55a2d1 JJ |
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" | |
5b3e6663 PB |
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)) | |
9a55a2d1 JJ |
1195 | (label_ref:SI (match_operand 2 "" "")))) |
1196 | (label_ref:SI (match_operand 3 "" "")))) | |
5b3e6663 | 1197 | (clobber (reg:CC CC_REGNUM)) |
f72d3365 | 1198 | (clobber (match_scratch:SI 4 "=&r")) |
5b3e6663 | 1199 | (clobber (match_scratch:SI 5 "=r")) |
9a55a2d1 | 1200 | (use (label_ref:SI (match_dup 2)))])] |
5b3e6663 PB |
1201 | "TARGET_THUMB2 && flag_pic" |
1202 | "* return thumb2_output_casesi(operands);" | |
1203 | [(set_attr "conds" "clob") | |
594726e4 JG |
1204 | (set_attr "length" "20") |
1205 | (set_attr "type" "multiple")] | |
5b3e6663 PB |
1206 | ) |
1207 | ||
7c19c715 | 1208 | (define_insn "*thumb2_return" |
f79b86a4 | 1209 | [(simple_return)] |
de954d6a | 1210 | "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())" |
f79b86a4 IB |
1211 | "* return output_return_instruction (const_true_rtx, true, false, true);" |
1212 | [(set_attr "type" "branch") | |
1213 | (set_attr "length" "4")] | |
7c19c715 JB |
1214 | ) |
1215 | ||
de954d6a AV |
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") | |
9f28fe39 | 1226 | (const_int 34) |
de954d6a AV |
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 | ||
5b3e6663 PB |
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 | ||
5b3e6663 PB |
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))] | |
d1b85efb PB |
1256 | "TARGET_THUMB2 && reload_completed |
1257 | && GET_CODE(operands[3]) != PLUS | |
1258 | && GET_CODE(operands[3]) != MINUS" | |
5b3e6663 PB |
1259 | "%I3%!\\t%0, %1, %2" |
1260 | [(set_attr "predicable" "yes") | |
594726e4 | 1261 | (set_attr "length" "2") |
1d61feeb | 1262 | (set_attr "type" "alu_sreg")] |
5b3e6663 PB |
1263 | ) |
1264 | ||
5b3e6663 | 1265 | (define_insn "*thumb2_shiftsi3_short" |
23d2a817 | 1266 | [(set (match_operand:SI 0 "low_register_operand" "=l,l") |
5b3e6663 | 1267 | (match_operator:SI 3 "shift_operator" |
23d2a817 RE |
1268 | [(match_operand:SI 1 "low_register_operand" "0,l") |
1269 | (match_operand:SI 2 "low_reg_or_int_operand" "l,M")])) | |
5b3e6663 PB |
1270 | (clobber (reg:CC CC_REGNUM))] |
1271 | "TARGET_THUMB2 && reload_completed | |
1272 | && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) | |
d435a4be | 1273 | || REG_P (operands[2]))" |
5b3e6663 PB |
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" "") | |
ae27ce51 QJ |
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")) | |
6e4150e1 | 1282 | (const_string "alu_shift_reg")))] |
5b3e6663 PB |
1283 | ) |
1284 | ||
953a18fb RE |
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")) | |
5b3e6663 PB |
1288 | (clobber (reg:CC CC_REGNUM))] |
1289 | "TARGET_THUMB2 && reload_completed" | |
1290 | "mov%!\t%0, %1" | |
1291 | [(set_attr "predicable" "yes") | |
594726e4 JG |
1292 | (set_attr "length" "2") |
1293 | (set_attr "type" "mov_imm")] | |
5b3e6663 PB |
1294 | ) |
1295 | ||
d1b85efb | 1296 | (define_insn "*thumb2_addsi_short" |
85f28bf1 JB |
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"))) | |
5b3e6663 PB |
1300 | (clobber (reg:CC CC_REGNUM))] |
1301 | "TARGET_THUMB2 && reload_completed" | |
1302 | "* | |
1303 | HOST_WIDE_INT val; | |
1304 | ||
d435a4be | 1305 | if (CONST_INT_P (operands[2])) |
d1b85efb PB |
1306 | val = INTVAL(operands[2]); |
1307 | else | |
1308 | val = 0; | |
1309 | ||
5b3e6663 PB |
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") | |
594726e4 | 1317 | (set_attr "length" "2") |
544f7fc8 YR |
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")])] | |
5b3e6663 PB |
1323 | ) |
1324 | ||
d1b85efb PB |
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") | |
594726e4 | 1333 | (set_attr "length" "2") |
1d61feeb | 1334 | (set_attr "type" "alu_sreg")] |
d1b85efb PB |
1335 | ) |
1336 | ||
e6bfe8a2 RE |
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 | ||
ce7b3761 | 1363 | (define_insn "thumb2_addsi3_compare0" |
54138d95 RH |
1364 | [(set (reg:CC_NZ CC_REGNUM) |
1365 | (compare:CC_NZ | |
dcd8b2ee JB |
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 | ||
d435a4be | 1375 | if (CONST_INT_P (operands[2])) |
dcd8b2ee JB |
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") | |
594726e4 | 1386 | (set_attr "length" "2,2,4") |
544f7fc8 YR |
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"))])] | |
dcd8b2ee JB |
1395 | ) |
1396 | ||
1397 | (define_insn "*thumb2_addsi3_compare0_scratch" | |
54138d95 RH |
1398 | [(set (reg:CC_NZ CC_REGNUM) |
1399 | (compare:CC_NZ | |
544f7fc8 YR |
1400 | (plus:SI (match_operand:SI 0 "s_register_operand" "l, r") |
1401 | (match_operand:SI 1 "arm_add_operand" "lPv,rIL")) | |
dcd8b2ee JB |
1402 | (const_int 0)))] |
1403 | "TARGET_THUMB2" | |
1404 | "* | |
1405 | HOST_WIDE_INT val; | |
1406 | ||
d435a4be | 1407 | if (CONST_INT_P (operands[1])) |
dcd8b2ee JB |
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") | |
544f7fc8 | 1418 | (set_attr "length" "2,4") |
b43482db | 1419 | (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "") |
544f7fc8 YR |
1420 | (const_string "alus_imm") |
1421 | (const_string "alus_sreg")))] | |
dcd8b2ee JB |
1422 | ) |
1423 | ||
7d31a807 MM |
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") | |
09485a08 | 1433 | (set_attr "type" "muls")]) |
7d31a807 MM |
1434 | |
1435 | (define_insn "*thumb2_mulsi_short_compare0" | |
54138d95 RH |
1436 | [(set (reg:CC_NZ CC_REGNUM) |
1437 | (compare:CC_NZ | |
7d31a807 MM |
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") | |
09485a08 | 1446 | (set_attr "type" "muls")]) |
7d31a807 MM |
1447 | |
1448 | (define_insn "*thumb2_mulsi_short_compare0_scratch" | |
54138d95 RH |
1449 | [(set (reg:CC_NZ CC_REGNUM) |
1450 | (compare:CC_NZ | |
7d31a807 MM |
1451 | (mult:SI (match_operand:SI 1 "register_operand" "%0") |
1452 | (match_operand:SI 2 "register_operand" "l")) | |
1453 | (const_int 0))) | |
3fc604fc | 1454 | (clobber (match_scratch:SI 0 "=l"))] |
7d31a807 MM |
1455 | "TARGET_THUMB2 && optimize_size" |
1456 | "muls\\t%0, %2, %0" | |
1457 | [(set_attr "length" "2") | |
09485a08 | 1458 | (set_attr "type" "muls")]) |
7d31a807 | 1459 | |
5b3e6663 PB |
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 | "* | |
98ac6510 | 1469 | if (get_attr_length (insn) == 2) |
5b3e6663 PB |
1470 | return \"cbz\\t%0, %l1\"; |
1471 | else | |
1472 | return \"cmp\\t%0, #0\;beq\\t%l1\"; | |
1473 | " | |
9e64a0bf | 1474 | [(set (attr "length") |
5b3e6663 PB |
1475 | (if_then_else |
1476 | (and (ge (minus (match_dup 1) (pc)) (const_int 2)) | |
98ac6510 | 1477 | (le (minus (match_dup 1) (pc)) (const_int 128)) |
b75b1be2 | 1478 | (not (match_test "which_alternative"))) |
5b3e6663 | 1479 | (const_int 2) |
594726e4 JG |
1480 | (const_int 8))) |
1481 | (set_attr "type" "branch,multiple")] | |
5b3e6663 PB |
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 | "* | |
98ac6510 | 1493 | if (get_attr_length (insn) == 2) |
5b3e6663 PB |
1494 | return \"cbnz\\t%0, %l1\"; |
1495 | else | |
1496 | return \"cmp\\t%0, #0\;bne\\t%l1\"; | |
1497 | " | |
9e64a0bf | 1498 | [(set (attr "length") |
5b3e6663 PB |
1499 | (if_then_else |
1500 | (and (ge (minus (match_dup 1) (pc)) (const_int 2)) | |
98ac6510 | 1501 | (le (minus (match_dup 1) (pc)) (const_int 128)) |
b75b1be2 | 1502 | (not (match_test "which_alternative"))) |
5b3e6663 | 1503 | (const_int 2) |
594726e4 JG |
1504 | (const_int 8))) |
1505 | (set_attr "type" "branch,multiple")] | |
5b3e6663 | 1506 | ) |
d1b85efb | 1507 | |
d1b85efb PB |
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") | |
594726e4 JG |
1515 | (set_attr "length" "2") |
1516 | (set_attr "type" "mvn_reg")] | |
d1b85efb PB |
1517 | ) |
1518 | ||
d1b85efb PB |
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" | |
4b04107b | 1524 | "rsb%!\t%0, %1, #0" |
d1b85efb | 1525 | [(set_attr "predicable" "yes") |
594726e4 | 1526 | (set_attr "length" "2") |
1d61feeb | 1527 | (set_attr "type" "alu_sreg")] |
d1b85efb PB |
1528 | ) |
1529 | ||
c29e2982 | 1530 | (define_insn "*orsi_notsi_si" |
a7994a57 RR |
1531 | [(set (match_operand:SI 0 "s_register_operand" "=r") |
1532 | (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) | |
64af62c2 | 1533 | (match_operand:SI 1 "s_register_operand" "r")))] |
a7994a57 RR |
1534 | "TARGET_THUMB2" |
1535 | "orn%?\\t%0, %1, %2" | |
95b97fac | 1536 | [(set_attr "predicable" "yes") |
594726e4 | 1537 | (set_attr "type" "logic_reg")] |
a7994a57 RR |
1538 | ) |
1539 | ||
c29e2982 | 1540 | (define_insn "*orsi_not_shiftsi_si" |
a7994a57 RR |
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") | |
ae27ce51 | 1550 | (set_attr "autodetect_type" "alu_shift_operator4")] |
a7994a57 RR |
1551 | ) |
1552 | ||
8850383b | 1553 | (define_peephole2 |
54138d95 RH |
1554 | [(set (match_operand:CC_NZ 0 "cc_register" "") |
1555 | (compare:CC_NZ (zero_extract:SI | |
8850383b RE |
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) | |
54138d95 | 1562 | (if_then_else (match_operator:CC_NZ 4 "equality_operator" |
8850383b RE |
1563 | [(match_dup 0) (const_int 0)]) |
1564 | (match_operand 5 "" "") | |
1565 | (match_operand 6 "" "")))] | |
1566 | "TARGET_THUMB2 | |
bae7adda KT |
1567 | && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32) |
1568 | && peep2_reg_dead_p (2, operands[0])" | |
8850383b | 1569 | [(parallel [(set (match_dup 0) |
54138d95 | 1570 | (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2)) |
8850383b RE |
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 | ") | |
333b67a9 | 1581 | |
ece53c91 | 1582 | (define_peephole2 |
54138d95 RH |
1583 | [(set (match_operand:CC_NZ 0 "cc_register" "") |
1584 | (compare:CC_NZ (zero_extract:SI | |
ece53c91 WG |
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) | |
54138d95 | 1591 | (if_then_else (match_operator:CC_NZ 4 "equality_operator" |
ece53c91 WG |
1592 | [(match_dup 0) (const_int 0)]) |
1593 | (match_operand 5 "" "") | |
1594 | (match_operand 6 "" "")))] | |
1595 | "TARGET_THUMB2 | |
bae7adda KT |
1596 | && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32) |
1597 | && peep2_reg_dead_p (2, operands[0])" | |
ece53c91 | 1598 | [(parallel [(set (match_dup 0) |
54138d95 RH |
1599 | (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2)) |
1600 | (const_int 0))) | |
ece53c91 WG |
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)))] | |
88c1612f WG |
1605 | " |
1606 | operands[2] = GEN_INT (32 - INTVAL (operands[2])); | |
ece53c91 | 1607 | ") |
ce7b3761 RE |
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 | |
1d0216c8 | 1613 | (use (match_operand 1 "" ""))] ; label |
ce7b3761 RE |
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 | |
d2ed233c AC |
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)) | |
ce7b3761 RE |
1627 | { |
1628 | rtx s0; | |
1629 | rtx bcomp; | |
1630 | rtx loc_ref; | |
1631 | rtx cc_reg; | |
1632 | rtx insn; | |
1633 | rtx cmp; | |
1634 | ||
ce7b3761 RE |
1635 | if (GET_MODE (operands[0]) != SImode) |
1636 | FAIL; | |
1637 | ||
1638 | s0 = operands [0]; | |
d2ed233c AC |
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 | ||
ce7b3761 RE |
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); | |
1d0216c8 | 1652 | loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]); |
f7df4a84 | 1653 | emit_jump_insn (gen_rtx_SET (pc_rtx, |
ce7b3761 RE |
1654 | gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, |
1655 | loc_ref, pc_rtx))); | |
1656 | DONE; | |
d2ed233c AC |
1657 | } |
1658 | else | |
1659 | FAIL; | |
ce7b3761 RE |
1660 | }") |
1661 | ||
9722215a MI |
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 | ) | |
60d616b1 MI |
1702 | |
1703 | (define_insn "thumb2_asrl" | |
1704 | [(set (match_operand:DI 0 "arm_general_register_operand" "+r") | |
1705 | (ashiftrt:DI (match_dup 0) | |
a968a40c | 1706 | (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))] |
60d616b1 MI |
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) | |
a968a40c | 1714 | (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))] |
60d616b1 MI |
1715 | "TARGET_HAVE_MVE" |
1716 | "lsll%?\\t%Q0, %R0, %1" | |
1717 | [(set_attr "predicable" "yes")]) | |
a968a40c MI |
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")]) | |
d2ed233c AC |
1726 | |
1727 | ;; Originally expanded by 'doloop_end'. | |
1728 | (define_insn "*doloop_end_internal" | |
38c57034 AC |
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))] | |
d2ed233c | 1737 | "TARGET_32BIT && TARGET_HAVE_LOB" |
38c57034 AC |
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")]) | |
d2ed233c AC |
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") |