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