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