Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/arm/thumb2.md @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 3bfb6c00c1e0 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 ;; ARM Thumb-2 Machine Description | |
2 ;; Copyright (C) 2007, 2008 Free Software Foundation, Inc. | |
3 ;; Written by CodeSourcery, LLC. | |
4 ;; | |
5 ;; This file is part of GCC. | |
6 ;; | |
7 ;; GCC is free software; you can redistribute it and/or modify it | |
8 ;; under the terms of the GNU General Public License as published by | |
9 ;; the Free Software Foundation; either version 3, or (at your option) | |
10 ;; any later version. | |
11 ;; | |
12 ;; GCC is distributed in the hope that it will be useful, but | |
13 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 ;; General Public License for more details. | |
16 ;; | |
17 ;; You should have received a copy of the GNU General Public License | |
18 ;; along with GCC; see the file COPYING3. If not see | |
19 ;; <http://www.gnu.org/licenses/>. */ | |
20 | |
21 ;; Note: Thumb-2 is the variant of the Thumb architecture that adds | |
22 ;; 32-bit encodings of [almost all of] the Arm instruction set. | |
23 ;; Some old documents refer to the relatively minor interworking | |
24 ;; changes made in armv5t as "thumb2". These are considered part | |
25 ;; the 16-bit Thumb-1 instruction set. | |
26 | |
27 (define_insn "*thumb2_incscc" | |
28 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
29 (plus:SI (match_operator:SI 2 "arm_comparison_operator" | |
30 [(match_operand:CC 3 "cc_register" "") (const_int 0)]) | |
31 (match_operand:SI 1 "s_register_operand" "0,?r")))] | |
32 "TARGET_THUMB2" | |
33 "@ | |
34 it\\t%d2\;add%d2\\t%0, %1, #1 | |
35 ite\\t%D2\;mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" | |
36 [(set_attr "conds" "use") | |
37 (set_attr "length" "6,10")] | |
38 ) | |
39 | |
40 (define_insn "*thumb2_decscc" | |
41 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
42 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") | |
43 (match_operator:SI 2 "arm_comparison_operator" | |
44 [(match_operand 3 "cc_register" "") (const_int 0)])))] | |
45 "TARGET_THUMB2" | |
46 "@ | |
47 it\\t%d2\;sub%d2\\t%0, %1, #1 | |
48 ite\\t%D2\;mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" | |
49 [(set_attr "conds" "use") | |
50 (set_attr "length" "6,10")] | |
51 ) | |
52 | |
53 ;; Thumb-2 only allows shift by constant on data processing instructions | |
54 (define_insn "*thumb_andsi_not_shiftsi_si" | |
55 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
56 (and:SI (not:SI (match_operator:SI 4 "shift_operator" | |
57 [(match_operand:SI 2 "s_register_operand" "r") | |
58 (match_operand:SI 3 "const_int_operand" "M")])) | |
59 (match_operand:SI 1 "s_register_operand" "r")))] | |
60 "TARGET_ARM" | |
61 "bic%?\\t%0, %1, %2%S4" | |
62 [(set_attr "predicable" "yes") | |
63 (set_attr "shift" "2") | |
64 (set_attr "type" "alu_shift")] | |
65 ) | |
66 | |
67 (define_insn "*thumb2_smaxsi3" | |
68 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | |
69 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") | |
70 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) | |
71 (clobber (reg:CC CC_REGNUM))] | |
72 "TARGET_THUMB2" | |
73 "@ | |
74 cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2 | |
75 cmp\\t%1, %2\;it\\tge\;movge\\t%0, %1 | |
76 cmp\\t%1, %2\;ite\\tge\;movge\\t%0, %1\;movlt\\t%0, %2" | |
77 [(set_attr "conds" "clob") | |
78 (set_attr "length" "10,10,14")] | |
79 ) | |
80 | |
81 (define_insn "*thumb2_sminsi3" | |
82 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | |
83 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") | |
84 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) | |
85 (clobber (reg:CC CC_REGNUM))] | |
86 "TARGET_THUMB2" | |
87 "@ | |
88 cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2 | |
89 cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %1 | |
90 cmp\\t%1, %2\;ite\\tlt\;movlt\\t%0, %1\;movge\\t%0, %2" | |
91 [(set_attr "conds" "clob") | |
92 (set_attr "length" "10,10,14")] | |
93 ) | |
94 | |
95 (define_insn "*thumb32_umaxsi3" | |
96 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | |
97 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") | |
98 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) | |
99 (clobber (reg:CC CC_REGNUM))] | |
100 "TARGET_THUMB2" | |
101 "@ | |
102 cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2 | |
103 cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %1 | |
104 cmp\\t%1, %2\;ite\\tcs\;movcs\\t%0, %1\;movcc\\t%0, %2" | |
105 [(set_attr "conds" "clob") | |
106 (set_attr "length" "10,10,14")] | |
107 ) | |
108 | |
109 (define_insn "*thumb2_uminsi3" | |
110 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | |
111 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") | |
112 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) | |
113 (clobber (reg:CC CC_REGNUM))] | |
114 "TARGET_THUMB2" | |
115 "@ | |
116 cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2 | |
117 cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %1 | |
118 cmp\\t%1, %2\;ite\\tcc\;movcc\\t%0, %1\;movcs\\t%0, %2" | |
119 [(set_attr "conds" "clob") | |
120 (set_attr "length" "10,10,14")] | |
121 ) | |
122 | |
123 (define_insn "*thumb2_notsi_shiftsi" | |
124 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
125 (not:SI (match_operator:SI 3 "shift_operator" | |
126 [(match_operand:SI 1 "s_register_operand" "r") | |
127 (match_operand:SI 2 "const_int_operand" "M")])))] | |
128 "TARGET_THUMB2" | |
129 "mvn%?\\t%0, %1%S3" | |
130 [(set_attr "predicable" "yes") | |
131 (set_attr "shift" "1") | |
132 (set_attr "type" "alu_shift")] | |
133 ) | |
134 | |
135 (define_insn "*thumb2_notsi_shiftsi_compare0" | |
136 [(set (reg:CC_NOOV CC_REGNUM) | |
137 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" | |
138 [(match_operand:SI 1 "s_register_operand" "r") | |
139 (match_operand:SI 2 "const_int_operand" "M")])) | |
140 (const_int 0))) | |
141 (set (match_operand:SI 0 "s_register_operand" "=r") | |
142 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] | |
143 "TARGET_THUMB2" | |
144 "mvn%.\\t%0, %1%S3" | |
145 [(set_attr "conds" "set") | |
146 (set_attr "shift" "1") | |
147 (set_attr "type" "alu_shift")] | |
148 ) | |
149 | |
150 (define_insn "*thumb2_not_shiftsi_compare0_scratch" | |
151 [(set (reg:CC_NOOV CC_REGNUM) | |
152 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" | |
153 [(match_operand:SI 1 "s_register_operand" "r") | |
154 (match_operand:SI 2 "const_int_operand" "M")])) | |
155 (const_int 0))) | |
156 (clobber (match_scratch:SI 0 "=r"))] | |
157 "TARGET_THUMB2" | |
158 "mvn%.\\t%0, %1%S3" | |
159 [(set_attr "conds" "set") | |
160 (set_attr "shift" "1") | |
161 (set_attr "type" "alu_shift")] | |
162 ) | |
163 | |
164 ;; Thumb-2 does not have rsc, so use a clever trick with shifter operands. | |
165 (define_insn "*thumb2_negdi2" | |
166 [(set (match_operand:DI 0 "s_register_operand" "=&r,r") | |
167 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0"))) | |
168 (clobber (reg:CC CC_REGNUM))] | |
169 "TARGET_THUMB2" | |
170 "negs\\t%Q0, %Q1\;sbc\\t%R0, %R1, %R1, lsl #1" | |
171 [(set_attr "conds" "clob") | |
172 (set_attr "length" "8")] | |
173 ) | |
174 | |
175 (define_insn "*thumb2_abssi2" | |
176 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") | |
177 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) | |
178 (clobber (reg:CC CC_REGNUM))] | |
179 "TARGET_THUMB2" | |
180 "@ | |
181 cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0 | |
182 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" | |
183 [(set_attr "conds" "clob,*") | |
184 (set_attr "shift" "1") | |
185 ;; predicable can't be set based on the variant, so left as no | |
186 (set_attr "length" "10,8")] | |
187 ) | |
188 | |
189 (define_insn "*thumb2_neg_abssi2" | |
190 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") | |
191 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) | |
192 (clobber (reg:CC CC_REGNUM))] | |
193 "TARGET_THUMB2" | |
194 "@ | |
195 cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0 | |
196 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" | |
197 [(set_attr "conds" "clob,*") | |
198 (set_attr "shift" "1") | |
199 ;; predicable can't be set based on the variant, so left as no | |
200 (set_attr "length" "10,8")] | |
201 ) | |
202 | |
203 (define_insn "*thumb2_movdi" | |
204 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m") | |
205 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))] | |
206 "TARGET_THUMB2 | |
207 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP)) | |
208 && !TARGET_IWMMXT" | |
209 "* | |
210 switch (which_alternative) | |
211 { | |
212 case 0: | |
213 case 1: | |
214 case 2: | |
215 return \"#\"; | |
216 default: | |
217 return output_move_double (operands); | |
218 } | |
219 " | |
220 [(set_attr "length" "8,12,16,8,8") | |
221 (set_attr "type" "*,*,*,load2,store2") | |
222 (set_attr "pool_range" "*,*,*,4096,*") | |
223 (set_attr "neg_pool_range" "*,*,*,0,*")] | |
224 ) | |
225 | |
226 (define_insn "*thumb2_movsi_insn" | |
227 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m") | |
228 (match_operand:SI 1 "general_operand" "rk ,I,K,N,mi,rk"))] | |
229 "TARGET_THUMB2 && ! TARGET_IWMMXT | |
230 && !(TARGET_HARD_FLOAT && TARGET_VFP) | |
231 && ( register_operand (operands[0], SImode) | |
232 || register_operand (operands[1], SImode))" | |
233 "@ | |
234 mov%?\\t%0, %1 | |
235 mov%?\\t%0, %1 | |
236 mvn%?\\t%0, #%B1 | |
237 movw%?\\t%0, %1 | |
238 ldr%?\\t%0, %1 | |
239 str%?\\t%1, %0" | |
240 [(set_attr "type" "*,*,*,*,load1,store1") | |
241 (set_attr "predicable" "yes") | |
242 (set_attr "pool_range" "*,*,*,*,4096,*") | |
243 (set_attr "neg_pool_range" "*,*,*,*,0,*")] | |
244 ) | |
245 | |
246 ;; ??? We can probably do better with thumb2 | |
247 (define_insn "pic_load_addr_thumb2" | |
248 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
249 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))] | |
250 "TARGET_THUMB2 && flag_pic" | |
251 "ldr%?\\t%0, %1" | |
252 [(set_attr "type" "load1") | |
253 (set_attr "pool_range" "4096") | |
254 (set_attr "neg_pool_range" "0")] | |
255 ) | |
256 | |
257 ;; Set reg to the address of this instruction plus four. The low two | |
258 ;; bits of the PC are always read as zero, so ensure the instructions is | |
259 ;; word aligned. | |
260 (define_insn "pic_load_dot_plus_four" | |
261 [(set (match_operand:SI 0 "register_operand" "=r") | |
262 (unspec:SI [(const_int 4) | |
263 (match_operand 1 "" "")] | |
264 UNSPEC_PIC_BASE))] | |
265 "TARGET_THUMB2" | |
266 "* | |
267 assemble_align(BITS_PER_WORD); | |
268 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\", | |
269 INTVAL (operands[1])); | |
270 /* We use adr because some buggy gas assemble add r8, pc, #0 | |
271 to add.w r8, pc, #0, not addw r8, pc, #0. */ | |
272 asm_fprintf (asm_out_file, \"\\tadr\\t%r, %LLPIC%d + 4\\n\", | |
273 REGNO(operands[0]), (int)INTVAL (operands[1])); | |
274 return \"\"; | |
275 " | |
276 [(set_attr "length" "6")] | |
277 ) | |
278 | |
279 ;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot | |
280 ;; of the messiness associated with the ARM patterns. | |
281 (define_insn "*thumb2_movhi_insn" | |
282 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") | |
283 (match_operand:HI 1 "general_operand" "rI,n,r,m"))] | |
284 "TARGET_THUMB2" | |
285 "@ | |
286 mov%?\\t%0, %1\\t%@ movhi | |
287 movw%?\\t%0, %L1\\t%@ movhi | |
288 str%(h%)\\t%1, %0\\t%@ movhi | |
289 ldr%(h%)\\t%0, %1\\t%@ movhi" | |
290 [(set_attr "type" "*,*,store1,load1") | |
291 (set_attr "predicable" "yes") | |
292 (set_attr "pool_range" "*,*,*,4096") | |
293 (set_attr "neg_pool_range" "*,*,*,250")] | |
294 ) | |
295 | |
296 (define_insn "*thumb2_movsf_soft_insn" | |
297 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") | |
298 (match_operand:SF 1 "general_operand" "r,mE,r"))] | |
299 "TARGET_THUMB2 | |
300 && TARGET_SOFT_FLOAT | |
301 && (GET_CODE (operands[0]) != MEM | |
302 || register_operand (operands[1], SFmode))" | |
303 "@ | |
304 mov%?\\t%0, %1 | |
305 ldr%?\\t%0, %1\\t%@ float | |
306 str%?\\t%1, %0\\t%@ float" | |
307 [(set_attr "predicable" "yes") | |
308 (set_attr "type" "*,load1,store1") | |
309 (set_attr "pool_range" "*,4096,*") | |
310 (set_attr "neg_pool_range" "*,0,*")] | |
311 ) | |
312 | |
313 (define_insn "*thumb2_movdf_soft_insn" | |
314 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m") | |
315 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))] | |
316 "TARGET_THUMB2 && TARGET_SOFT_FLOAT | |
317 && ( register_operand (operands[0], DFmode) | |
318 || register_operand (operands[1], DFmode))" | |
319 "* | |
320 switch (which_alternative) | |
321 { | |
322 case 0: | |
323 case 1: | |
324 case 2: | |
325 return \"#\"; | |
326 default: | |
327 return output_move_double (operands); | |
328 } | |
329 " | |
330 [(set_attr "length" "8,12,16,8,8") | |
331 (set_attr "type" "*,*,*,load2,store2") | |
332 (set_attr "pool_range" "1020") | |
333 (set_attr "neg_pool_range" "0")] | |
334 ) | |
335 | |
336 (define_insn "*thumb2_cmpsi_shiftsi" | |
337 [(set (reg:CC CC_REGNUM) | |
338 (compare:CC (match_operand:SI 0 "s_register_operand" "r") | |
339 (match_operator:SI 3 "shift_operator" | |
340 [(match_operand:SI 1 "s_register_operand" "r") | |
341 (match_operand:SI 2 "const_int_operand" "M")])))] | |
342 "TARGET_THUMB2" | |
343 "cmp%?\\t%0, %1%S3" | |
344 [(set_attr "conds" "set") | |
345 (set_attr "shift" "1") | |
346 (set_attr "type" "alu_shift")] | |
347 ) | |
348 | |
349 (define_insn "*thumb2_cmpsi_shiftsi_swp" | |
350 [(set (reg:CC_SWP CC_REGNUM) | |
351 (compare:CC_SWP (match_operator:SI 3 "shift_operator" | |
352 [(match_operand:SI 1 "s_register_operand" "r") | |
353 (match_operand:SI 2 "const_int_operand" "M")]) | |
354 (match_operand:SI 0 "s_register_operand" "r")))] | |
355 "TARGET_THUMB2" | |
356 "cmp%?\\t%0, %1%S3" | |
357 [(set_attr "conds" "set") | |
358 (set_attr "shift" "1") | |
359 (set_attr "type" "alu_shift")] | |
360 ) | |
361 | |
362 (define_insn "*thumb2_cmpsi_neg_shiftsi" | |
363 [(set (reg:CC CC_REGNUM) | |
364 (compare:CC (match_operand:SI 0 "s_register_operand" "r") | |
365 (neg:SI (match_operator:SI 3 "shift_operator" | |
366 [(match_operand:SI 1 "s_register_operand" "r") | |
367 (match_operand:SI 2 "const_int_operand" "M")]))))] | |
368 "TARGET_THUMB2" | |
369 "cmn%?\\t%0, %1%S3" | |
370 [(set_attr "conds" "set") | |
371 (set_attr "shift" "1") | |
372 (set_attr "type" "alu_shift")] | |
373 ) | |
374 | |
375 (define_insn "*thumb2_mov_scc" | |
376 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
377 (match_operator:SI 1 "arm_comparison_operator" | |
378 [(match_operand 2 "cc_register" "") (const_int 0)]))] | |
379 "TARGET_THUMB2" | |
380 "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1" | |
381 [(set_attr "conds" "use") | |
382 (set_attr "length" "10")] | |
383 ) | |
384 | |
385 (define_insn "*thumb2_mov_negscc" | |
386 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
387 (neg:SI (match_operator:SI 1 "arm_comparison_operator" | |
388 [(match_operand 2 "cc_register" "") (const_int 0)])))] | |
389 "TARGET_THUMB2" | |
390 "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" | |
391 [(set_attr "conds" "use") | |
392 (set_attr "length" "10")] | |
393 ) | |
394 | |
395 (define_insn "*thumb2_mov_notscc" | |
396 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
397 (not:SI (match_operator:SI 1 "arm_comparison_operator" | |
398 [(match_operand 2 "cc_register" "") (const_int 0)])))] | |
399 "TARGET_THUMB2" | |
400 "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #1" | |
401 [(set_attr "conds" "use") | |
402 (set_attr "length" "10")] | |
403 ) | |
404 | |
405 (define_insn "*thumb2_movsicc_insn" | |
406 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") | |
407 (if_then_else:SI | |
408 (match_operator 3 "arm_comparison_operator" | |
409 [(match_operand 4 "cc_register" "") (const_int 0)]) | |
410 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") | |
411 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] | |
412 "TARGET_THUMB2" | |
413 "@ | |
414 it\\t%D3\;mov%D3\\t%0, %2 | |
415 it\\t%D3\;mvn%D3\\t%0, #%B2 | |
416 it\\t%d3\;mov%d3\\t%0, %1 | |
417 it\\t%d3\;mvn%d3\\t%0, #%B1 | |
418 ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2 | |
419 ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 | |
420 ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 | |
421 ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" | |
422 [(set_attr "length" "6,6,6,6,10,10,10,10") | |
423 (set_attr "conds" "use")] | |
424 ) | |
425 | |
426 (define_insn "*thumb2_movsfcc_soft_insn" | |
427 [(set (match_operand:SF 0 "s_register_operand" "=r,r") | |
428 (if_then_else:SF (match_operator 3 "arm_comparison_operator" | |
429 [(match_operand 4 "cc_register" "") (const_int 0)]) | |
430 (match_operand:SF 1 "s_register_operand" "0,r") | |
431 (match_operand:SF 2 "s_register_operand" "r,0")))] | |
432 "TARGET_THUMB2 && TARGET_SOFT_FLOAT" | |
433 "@ | |
434 it\\t%D3\;mov%D3\\t%0, %2 | |
435 it\\t%d3\;mov%d3\\t%0, %1" | |
436 [(set_attr "length" "6,6") | |
437 (set_attr "conds" "use")] | |
438 ) | |
439 | |
440 (define_insn "*call_reg_thumb2" | |
441 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) | |
442 (match_operand 1 "" "")) | |
443 (use (match_operand 2 "" "")) | |
444 (clobber (reg:SI LR_REGNUM))] | |
445 "TARGET_THUMB2" | |
446 "blx%?\\t%0" | |
447 [(set_attr "type" "call")] | |
448 ) | |
449 | |
450 (define_insn "*call_value_reg_thumb2" | |
451 [(set (match_operand 0 "" "") | |
452 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) | |
453 (match_operand 2 "" ""))) | |
454 (use (match_operand 3 "" "")) | |
455 (clobber (reg:SI LR_REGNUM))] | |
456 "TARGET_THUMB2" | |
457 "blx\\t%1" | |
458 [(set_attr "type" "call")] | |
459 ) | |
460 | |
461 (define_insn "*thumb2_indirect_jump" | |
462 [(set (pc) | |
463 (match_operand:SI 0 "register_operand" "l*r"))] | |
464 "TARGET_THUMB2" | |
465 "bx\\t%0" | |
466 [(set_attr "conds" "clob")] | |
467 ) | |
468 ;; Don't define thumb2_load_indirect_jump because we can't guarantee label | |
469 ;; addresses will have the thumb bit set correctly. | |
470 | |
471 | |
472 ;; Patterns to allow combination of arithmetic, cond code and shifts | |
473 | |
474 (define_insn "*thumb2_arith_shiftsi" | |
475 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
476 (match_operator:SI 1 "shiftable_operator" | |
477 [(match_operator:SI 3 "shift_operator" | |
478 [(match_operand:SI 4 "s_register_operand" "r") | |
479 (match_operand:SI 5 "const_int_operand" "M")]) | |
480 (match_operand:SI 2 "s_register_operand" "r")]))] | |
481 "TARGET_THUMB2" | |
482 "%i1%?\\t%0, %2, %4%S3" | |
483 [(set_attr "predicable" "yes") | |
484 (set_attr "shift" "4") | |
485 (set_attr "type" "alu_shift")] | |
486 ) | |
487 | |
488 ;; ??? What does this splitter do? Copied from the ARM version | |
489 (define_split | |
490 [(set (match_operand:SI 0 "s_register_operand" "") | |
491 (match_operator:SI 1 "shiftable_operator" | |
492 [(match_operator:SI 2 "shiftable_operator" | |
493 [(match_operator:SI 3 "shift_operator" | |
494 [(match_operand:SI 4 "s_register_operand" "") | |
495 (match_operand:SI 5 "const_int_operand" "")]) | |
496 (match_operand:SI 6 "s_register_operand" "")]) | |
497 (match_operand:SI 7 "arm_rhs_operand" "")])) | |
498 (clobber (match_operand:SI 8 "s_register_operand" ""))] | |
499 "TARGET_32BIT" | |
500 [(set (match_dup 8) | |
501 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) | |
502 (match_dup 6)])) | |
503 (set (match_dup 0) | |
504 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))] | |
505 "") | |
506 | |
507 (define_insn "*thumb2_arith_shiftsi_compare0" | |
508 [(set (reg:CC_NOOV CC_REGNUM) | |
509 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" | |
510 [(match_operator:SI 3 "shift_operator" | |
511 [(match_operand:SI 4 "s_register_operand" "r") | |
512 (match_operand:SI 5 "const_int_operand" "M")]) | |
513 (match_operand:SI 2 "s_register_operand" "r")]) | |
514 (const_int 0))) | |
515 (set (match_operand:SI 0 "s_register_operand" "=r") | |
516 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) | |
517 (match_dup 2)]))] | |
518 "TARGET_32BIT" | |
519 "%i1%.\\t%0, %2, %4%S3" | |
520 [(set_attr "conds" "set") | |
521 (set_attr "shift" "4") | |
522 (set_attr "type" "alu_shift")] | |
523 ) | |
524 | |
525 (define_insn "*thumb2_arith_shiftsi_compare0_scratch" | |
526 [(set (reg:CC_NOOV CC_REGNUM) | |
527 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" | |
528 [(match_operator:SI 3 "shift_operator" | |
529 [(match_operand:SI 4 "s_register_operand" "r") | |
530 (match_operand:SI 5 "const_int_operand" "M")]) | |
531 (match_operand:SI 2 "s_register_operand" "r")]) | |
532 (const_int 0))) | |
533 (clobber (match_scratch:SI 0 "=r"))] | |
534 "TARGET_THUMB2" | |
535 "%i1%.\\t%0, %2, %4%S3" | |
536 [(set_attr "conds" "set") | |
537 (set_attr "shift" "4") | |
538 (set_attr "type" "alu_shift")] | |
539 ) | |
540 | |
541 (define_insn "*thumb2_sub_shiftsi" | |
542 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
543 (minus:SI (match_operand:SI 1 "s_register_operand" "r") | |
544 (match_operator:SI 2 "shift_operator" | |
545 [(match_operand:SI 3 "s_register_operand" "r") | |
546 (match_operand:SI 4 "const_int_operand" "M")])))] | |
547 "TARGET_THUMB2" | |
548 "sub%?\\t%0, %1, %3%S2" | |
549 [(set_attr "predicable" "yes") | |
550 (set_attr "shift" "3") | |
551 (set_attr "type" "alu_shift")] | |
552 ) | |
553 | |
554 (define_insn "*thumb2_sub_shiftsi_compare0" | |
555 [(set (reg:CC_NOOV CC_REGNUM) | |
556 (compare:CC_NOOV | |
557 (minus:SI (match_operand:SI 1 "s_register_operand" "r") | |
558 (match_operator:SI 2 "shift_operator" | |
559 [(match_operand:SI 3 "s_register_operand" "r") | |
560 (match_operand:SI 4 "const_int_operand" "M")])) | |
561 (const_int 0))) | |
562 (set (match_operand:SI 0 "s_register_operand" "=r") | |
563 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) | |
564 (match_dup 4)])))] | |
565 "TARGET_THUMB2" | |
566 "sub%.\\t%0, %1, %3%S2" | |
567 [(set_attr "conds" "set") | |
568 (set_attr "shift" "3") | |
569 (set_attr "type" "alu_shift")] | |
570 ) | |
571 | |
572 (define_insn "*thumb2_sub_shiftsi_compare0_scratch" | |
573 [(set (reg:CC_NOOV CC_REGNUM) | |
574 (compare:CC_NOOV | |
575 (minus:SI (match_operand:SI 1 "s_register_operand" "r") | |
576 (match_operator:SI 2 "shift_operator" | |
577 [(match_operand:SI 3 "s_register_operand" "r") | |
578 (match_operand:SI 4 "const_int_operand" "M")])) | |
579 (const_int 0))) | |
580 (clobber (match_scratch:SI 0 "=r"))] | |
581 "TARGET_THUMB2" | |
582 "sub%.\\t%0, %1, %3%S2" | |
583 [(set_attr "conds" "set") | |
584 (set_attr "shift" "3") | |
585 (set_attr "type" "alu_shift")] | |
586 ) | |
587 | |
588 (define_insn "*thumb2_and_scc" | |
589 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
590 (and:SI (match_operator:SI 1 "arm_comparison_operator" | |
591 [(match_operand 3 "cc_register" "") (const_int 0)]) | |
592 (match_operand:SI 2 "s_register_operand" "r")))] | |
593 "TARGET_THUMB2" | |
594 "ite\\t%D1\;mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" | |
595 [(set_attr "conds" "use") | |
596 (set_attr "length" "10")] | |
597 ) | |
598 | |
599 (define_insn "*thumb2_ior_scc" | |
600 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
601 (ior:SI (match_operator:SI 2 "arm_comparison_operator" | |
602 [(match_operand 3 "cc_register" "") (const_int 0)]) | |
603 (match_operand:SI 1 "s_register_operand" "0,?r")))] | |
604 "TARGET_THUMB2" | |
605 "@ | |
606 it\\t%d2\;orr%d2\\t%0, %1, #1 | |
607 ite\\t%D2\;mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" | |
608 [(set_attr "conds" "use") | |
609 (set_attr "length" "6,10")] | |
610 ) | |
611 | |
612 (define_insn "*thumb2_compare_scc" | |
613 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
614 (match_operator:SI 1 "arm_comparison_operator" | |
615 [(match_operand:SI 2 "s_register_operand" "r,r") | |
616 (match_operand:SI 3 "arm_add_operand" "rI,L")])) | |
617 (clobber (reg:CC CC_REGNUM))] | |
618 "TARGET_THUMB2" | |
619 "* | |
620 if (operands[3] == const0_rtx) | |
621 { | |
622 if (GET_CODE (operands[1]) == LT) | |
623 return \"lsr\\t%0, %2, #31\"; | |
624 | |
625 if (GET_CODE (operands[1]) == GE) | |
626 return \"mvn\\t%0, %2\;lsr\\t%0, %0, #31\"; | |
627 | |
628 if (GET_CODE (operands[1]) == EQ) | |
629 return \"rsbs\\t%0, %2, #1\;it\\tcc\;movcc\\t%0, #0\"; | |
630 } | |
631 | |
632 if (GET_CODE (operands[1]) == NE) | |
633 { | |
634 if (which_alternative == 1) | |
635 return \"adds\\t%0, %2, #%n3\;it\\tne\;movne\\t%0, #1\"; | |
636 return \"subs\\t%0, %2, %3\;it\\tne\;movne\\t%0, #1\"; | |
637 } | |
638 if (which_alternative == 1) | |
639 output_asm_insn (\"cmn\\t%2, #%n3\", operands); | |
640 else | |
641 output_asm_insn (\"cmp\\t%2, %3\", operands); | |
642 return \"ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; | |
643 " | |
644 [(set_attr "conds" "clob") | |
645 (set_attr "length" "14")] | |
646 ) | |
647 | |
648 (define_insn "*thumb2_cond_move" | |
649 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | |
650 (if_then_else:SI (match_operator 3 "equality_operator" | |
651 [(match_operator 4 "arm_comparison_operator" | |
652 [(match_operand 5 "cc_register" "") (const_int 0)]) | |
653 (const_int 0)]) | |
654 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") | |
655 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] | |
656 "TARGET_THUMB2" | |
657 "* | |
658 if (GET_CODE (operands[3]) == NE) | |
659 { | |
660 if (which_alternative != 1) | |
661 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands); | |
662 if (which_alternative != 0) | |
663 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands); | |
664 return \"\"; | |
665 } | |
666 switch (which_alternative) | |
667 { | |
668 case 0: | |
669 output_asm_insn (\"it\\t%d4\", operands); | |
670 break; | |
671 case 1: | |
672 output_asm_insn (\"it\\t%D4\", operands); | |
673 break; | |
674 case 2: | |
675 output_asm_insn (\"ite\\t%D4\", operands); | |
676 break; | |
677 default: | |
678 abort(); | |
679 } | |
680 if (which_alternative != 0) | |
681 output_asm_insn (\"mov%D4\\t%0, %1\", operands); | |
682 if (which_alternative != 1) | |
683 output_asm_insn (\"mov%d4\\t%0, %2\", operands); | |
684 return \"\"; | |
685 " | |
686 [(set_attr "conds" "use") | |
687 (set_attr "length" "6,6,10")] | |
688 ) | |
689 | |
690 (define_insn "*thumb2_cond_arith" | |
691 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
692 (match_operator:SI 5 "shiftable_operator" | |
693 [(match_operator:SI 4 "arm_comparison_operator" | |
694 [(match_operand:SI 2 "s_register_operand" "r,r") | |
695 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) | |
696 (match_operand:SI 1 "s_register_operand" "0,?r")])) | |
697 (clobber (reg:CC CC_REGNUM))] | |
698 "TARGET_THUMB2" | |
699 "* | |
700 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) | |
701 return \"%i5\\t%0, %1, %2, lsr #31\"; | |
702 | |
703 output_asm_insn (\"cmp\\t%2, %3\", operands); | |
704 if (GET_CODE (operands[5]) == AND) | |
705 { | |
706 output_asm_insn (\"ite\\t%D4\", operands); | |
707 output_asm_insn (\"mov%D4\\t%0, #0\", operands); | |
708 } | |
709 else if (GET_CODE (operands[5]) == MINUS) | |
710 { | |
711 output_asm_insn (\"ite\\t%D4\", operands); | |
712 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); | |
713 } | |
714 else if (which_alternative != 0) | |
715 { | |
716 output_asm_insn (\"ite\\t%D4\", operands); | |
717 output_asm_insn (\"mov%D4\\t%0, %1\", operands); | |
718 } | |
719 else | |
720 output_asm_insn (\"it\\t%d4\", operands); | |
721 return \"%i5%d4\\t%0, %1, #1\"; | |
722 " | |
723 [(set_attr "conds" "clob") | |
724 (set_attr "length" "14")] | |
725 ) | |
726 | |
727 (define_insn "*thumb2_cond_sub" | |
728 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
729 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") | |
730 (match_operator:SI 4 "arm_comparison_operator" | |
731 [(match_operand:SI 2 "s_register_operand" "r,r") | |
732 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) | |
733 (clobber (reg:CC CC_REGNUM))] | |
734 "TARGET_THUMB2" | |
735 "* | |
736 output_asm_insn (\"cmp\\t%2, %3\", operands); | |
737 if (which_alternative != 0) | |
738 { | |
739 output_asm_insn (\"ite\\t%D4\", operands); | |
740 output_asm_insn (\"mov%D4\\t%0, %1\", operands); | |
741 } | |
742 else | |
743 output_asm_insn (\"it\\t%d4\", operands); | |
744 return \"sub%d4\\t%0, %1, #1\"; | |
745 " | |
746 [(set_attr "conds" "clob") | |
747 (set_attr "length" "10,14")] | |
748 ) | |
749 | |
750 (define_insn "*thumb2_negscc" | |
751 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
752 (neg:SI (match_operator 3 "arm_comparison_operator" | |
753 [(match_operand:SI 1 "s_register_operand" "r") | |
754 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) | |
755 (clobber (reg:CC CC_REGNUM))] | |
756 "TARGET_THUMB2" | |
757 "* | |
758 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx) | |
759 return \"asr\\t%0, %1, #31\"; | |
760 | |
761 if (GET_CODE (operands[3]) == NE) | |
762 return \"subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0\"; | |
763 | |
764 output_asm_insn (\"cmp\\t%1, %2\", operands); | |
765 output_asm_insn (\"ite\\t%D3\", operands); | |
766 output_asm_insn (\"mov%D3\\t%0, #0\", operands); | |
767 return \"mvn%d3\\t%0, #0\"; | |
768 " | |
769 [(set_attr "conds" "clob") | |
770 (set_attr "length" "14")] | |
771 ) | |
772 | |
773 (define_insn "*thumb2_movcond" | |
774 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") | |
775 (if_then_else:SI | |
776 (match_operator 5 "arm_comparison_operator" | |
777 [(match_operand:SI 3 "s_register_operand" "r,r,r") | |
778 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) | |
779 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") | |
780 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) | |
781 (clobber (reg:CC CC_REGNUM))] | |
782 "TARGET_THUMB2" | |
783 "* | |
784 if (GET_CODE (operands[5]) == LT | |
785 && (operands[4] == const0_rtx)) | |
786 { | |
787 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) | |
788 { | |
789 if (operands[2] == const0_rtx) | |
790 return \"and\\t%0, %1, %3, asr #31\"; | |
791 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\"; | |
792 } | |
793 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) | |
794 { | |
795 if (operands[1] == const0_rtx) | |
796 return \"bic\\t%0, %2, %3, asr #31\"; | |
797 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\"; | |
798 } | |
799 /* The only case that falls through to here is when both ops 1 & 2 | |
800 are constants. */ | |
801 } | |
802 | |
803 if (GET_CODE (operands[5]) == GE | |
804 && (operands[4] == const0_rtx)) | |
805 { | |
806 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) | |
807 { | |
808 if (operands[2] == const0_rtx) | |
809 return \"bic\\t%0, %1, %3, asr #31\"; | |
810 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\"; | |
811 } | |
812 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) | |
813 { | |
814 if (operands[1] == const0_rtx) | |
815 return \"and\\t%0, %2, %3, asr #31\"; | |
816 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\"; | |
817 } | |
818 /* The only case that falls through to here is when both ops 1 & 2 | |
819 are constants. */ | |
820 } | |
821 if (GET_CODE (operands[4]) == CONST_INT | |
822 && !const_ok_for_arm (INTVAL (operands[4]))) | |
823 output_asm_insn (\"cmn\\t%3, #%n4\", operands); | |
824 else | |
825 output_asm_insn (\"cmp\\t%3, %4\", operands); | |
826 switch (which_alternative) | |
827 { | |
828 case 0: | |
829 output_asm_insn (\"it\\t%D5\", operands); | |
830 break; | |
831 case 1: | |
832 output_asm_insn (\"it\\t%d5\", operands); | |
833 break; | |
834 case 2: | |
835 output_asm_insn (\"ite\\t%d5\", operands); | |
836 break; | |
837 default: | |
838 abort(); | |
839 } | |
840 if (which_alternative != 0) | |
841 output_asm_insn (\"mov%d5\\t%0, %1\", operands); | |
842 if (which_alternative != 1) | |
843 output_asm_insn (\"mov%D5\\t%0, %2\", operands); | |
844 return \"\"; | |
845 " | |
846 [(set_attr "conds" "clob") | |
847 (set_attr "length" "10,10,14")] | |
848 ) | |
849 | |
850 ;; Zero and sign extension instructions. | |
851 | |
852 (define_insn "*thumb2_zero_extendsidi2" | |
853 [(set (match_operand:DI 0 "s_register_operand" "=r") | |
854 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] | |
855 "TARGET_THUMB2" | |
856 "* | |
857 /* ??? Output both instructions unconditionally, otherwise the conditional | |
858 execution insn counter gets confused. | |
859 if (REGNO (operands[1]) | |
860 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) */ | |
861 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); | |
862 return \"mov%?\\t%R0, #0\"; | |
863 " | |
864 [(set_attr "length" "8") | |
865 (set_attr "ce_count" "2") | |
866 (set_attr "predicable" "yes")] | |
867 ) | |
868 | |
869 (define_insn "*thumb2_zero_extendqidi2" | |
870 [(set (match_operand:DI 0 "s_register_operand" "=r,r") | |
871 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
872 "TARGET_THUMB2" | |
873 "@ | |
874 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0 | |
875 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0" | |
876 [(set_attr "length" "8") | |
877 (set_attr "ce_count" "2") | |
878 (set_attr "predicable" "yes") | |
879 (set_attr "type" "*,load_byte") | |
880 (set_attr "pool_range" "*,4092") | |
881 (set_attr "neg_pool_range" "*,250")] | |
882 ) | |
883 | |
884 (define_insn "*thumb2_extendsidi2" | |
885 [(set (match_operand:DI 0 "s_register_operand" "=r") | |
886 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] | |
887 "TARGET_THUMB2" | |
888 "* | |
889 /* ??? Output both instructions unconditionally, otherwise the conditional | |
890 execution insn counter gets confused. | |
891 if (REGNO (operands[1]) | |
892 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) */ | |
893 output_asm_insn (\"mov%?\\t%Q0, %1\", operands); | |
894 return \"asr%?\\t%R0, %Q0, #31\"; | |
895 " | |
896 [(set_attr "length" "8") | |
897 (set_attr "ce_count" "2") | |
898 (set_attr "shift" "1") | |
899 (set_attr "predicable" "yes")] | |
900 ) | |
901 | |
902 ;; All supported Thumb2 implementations are armv6, so only that case is | |
903 ;; provided. | |
904 (define_insn "*thumb2_extendqisi_v6" | |
905 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
906 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
907 "TARGET_THUMB2 && arm_arch6" | |
908 "@ | |
909 sxtb%?\\t%0, %1 | |
910 ldr%(sb%)\\t%0, %1" | |
911 [(set_attr "type" "alu_shift,load_byte") | |
912 (set_attr "predicable" "yes") | |
913 (set_attr "pool_range" "*,4096") | |
914 (set_attr "neg_pool_range" "*,250")] | |
915 ) | |
916 | |
917 (define_insn "*thumb2_zero_extendhisi2_v6" | |
918 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
919 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | |
920 "TARGET_THUMB2 && arm_arch6" | |
921 "@ | |
922 uxth%?\\t%0, %1 | |
923 ldr%(h%)\\t%0, %1" | |
924 [(set_attr "type" "alu_shift,load_byte") | |
925 (set_attr "predicable" "yes") | |
926 (set_attr "pool_range" "*,4096") | |
927 (set_attr "neg_pool_range" "*,250")] | |
928 ) | |
929 | |
930 (define_insn "*thumb2_zero_extendqisi2_v6" | |
931 [(set (match_operand:SI 0 "s_register_operand" "=r,r") | |
932 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
933 "TARGET_THUMB2 && arm_arch6" | |
934 "@ | |
935 uxtb%(%)\\t%0, %1 | |
936 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" | |
937 [(set_attr "type" "alu_shift,load_byte") | |
938 (set_attr "predicable" "yes") | |
939 (set_attr "pool_range" "*,4096") | |
940 (set_attr "neg_pool_range" "*,250")] | |
941 ) | |
942 | |
943 (define_insn "thumb2_casesi_internal" | |
944 [(parallel [(set (pc) | |
945 (if_then_else | |
946 (leu (match_operand:SI 0 "s_register_operand" "r") | |
947 (match_operand:SI 1 "arm_rhs_operand" "rI")) | |
948 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) | |
949 (label_ref (match_operand 2 "" "")))) | |
950 (label_ref (match_operand 3 "" "")))) | |
951 (clobber (reg:CC CC_REGNUM)) | |
952 (clobber (match_scratch:SI 4 "=&r")) | |
953 (use (label_ref (match_dup 2)))])] | |
954 "TARGET_THUMB2 && !flag_pic" | |
955 "* return thumb2_output_casesi(operands);" | |
956 [(set_attr "conds" "clob") | |
957 (set_attr "length" "16")] | |
958 ) | |
959 | |
960 (define_insn "thumb2_casesi_internal_pic" | |
961 [(parallel [(set (pc) | |
962 (if_then_else | |
963 (leu (match_operand:SI 0 "s_register_operand" "r") | |
964 (match_operand:SI 1 "arm_rhs_operand" "rI")) | |
965 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) | |
966 (label_ref (match_operand 2 "" "")))) | |
967 (label_ref (match_operand 3 "" "")))) | |
968 (clobber (reg:CC CC_REGNUM)) | |
969 (clobber (match_scratch:SI 4 "=&r")) | |
970 (clobber (match_scratch:SI 5 "=r")) | |
971 (use (label_ref (match_dup 2)))])] | |
972 "TARGET_THUMB2 && flag_pic" | |
973 "* return thumb2_output_casesi(operands);" | |
974 [(set_attr "conds" "clob") | |
975 (set_attr "length" "20")] | |
976 ) | |
977 | |
978 (define_insn_and_split "thumb2_eh_return" | |
979 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")] | |
980 VUNSPEC_EH_RETURN) | |
981 (clobber (match_scratch:SI 1 "=&r"))] | |
982 "TARGET_THUMB2" | |
983 "#" | |
984 "&& reload_completed" | |
985 [(const_int 0)] | |
986 " | |
987 { | |
988 thumb_set_return_address (operands[0], operands[1]); | |
989 DONE; | |
990 }" | |
991 ) | |
992 | |
993 ;; Peepholes and insns for 16-bit flag clobbering instructions. | |
994 ;; The conditional forms of these instructions do not clobber CC. | |
995 ;; However by the time peepholes are run it is probably too late to do | |
996 ;; anything useful with this information. | |
997 (define_peephole2 | |
998 [(set (match_operand:SI 0 "low_register_operand" "") | |
999 (match_operator:SI 3 "thumb_16bit_operator" | |
1000 [(match_operand:SI 1 "low_register_operand" "") | |
1001 (match_operand:SI 2 "low_register_operand" "")]))] | |
1002 "TARGET_THUMB2 | |
1003 && (rtx_equal_p(operands[0], operands[1]) | |
1004 || GET_CODE(operands[3]) == PLUS | |
1005 || GET_CODE(operands[3]) == MINUS) | |
1006 && peep2_regno_dead_p(0, CC_REGNUM)" | |
1007 [(parallel | |
1008 [(set (match_dup 0) | |
1009 (match_op_dup 3 | |
1010 [(match_dup 1) | |
1011 (match_dup 2)])) | |
1012 (clobber (reg:CC CC_REGNUM))])] | |
1013 "" | |
1014 ) | |
1015 | |
1016 (define_insn "*thumb2_alusi3_short" | |
1017 [(set (match_operand:SI 0 "s_register_operand" "=l") | |
1018 (match_operator:SI 3 "thumb_16bit_operator" | |
1019 [(match_operand:SI 1 "s_register_operand" "0") | |
1020 (match_operand:SI 2 "s_register_operand" "l")])) | |
1021 (clobber (reg:CC CC_REGNUM))] | |
1022 "TARGET_THUMB2 && reload_completed | |
1023 && GET_CODE(operands[3]) != PLUS | |
1024 && GET_CODE(operands[3]) != MINUS" | |
1025 "%I3%!\\t%0, %1, %2" | |
1026 [(set_attr "predicable" "yes") | |
1027 (set_attr "length" "2")] | |
1028 ) | |
1029 | |
1030 ;; Similarly for 16-bit shift instructions | |
1031 ;; There is no 16-bit rotate by immediate instruction. | |
1032 (define_peephole2 | |
1033 [(set (match_operand:SI 0 "low_register_operand" "") | |
1034 (match_operator:SI 3 "shift_operator" | |
1035 [(match_operand:SI 1 "low_register_operand" "") | |
1036 (match_operand:SI 2 "low_reg_or_int_operand" "")]))] | |
1037 "TARGET_THUMB2 | |
1038 && peep2_regno_dead_p(0, CC_REGNUM) | |
1039 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) | |
1040 || REG_P(operands[2]))" | |
1041 [(parallel | |
1042 [(set (match_dup 0) | |
1043 (match_op_dup 3 | |
1044 [(match_dup 1) | |
1045 (match_dup 2)])) | |
1046 (clobber (reg:CC CC_REGNUM))])] | |
1047 "" | |
1048 ) | |
1049 | |
1050 (define_insn "*thumb2_shiftsi3_short" | |
1051 [(set (match_operand:SI 0 "low_register_operand" "=l") | |
1052 (match_operator:SI 3 "shift_operator" | |
1053 [(match_operand:SI 1 "low_register_operand" "l") | |
1054 (match_operand:SI 2 "low_reg_or_int_operand" "lM")])) | |
1055 (clobber (reg:CC CC_REGNUM))] | |
1056 "TARGET_THUMB2 && reload_completed | |
1057 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) | |
1058 || REG_P(operands[2]))" | |
1059 "* return arm_output_shift(operands, 2);" | |
1060 [(set_attr "predicable" "yes") | |
1061 (set_attr "shift" "1") | |
1062 (set_attr "length" "2") | |
1063 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") | |
1064 (const_string "alu_shift") | |
1065 (const_string "alu_shift_reg")))] | |
1066 ) | |
1067 | |
1068 ;; 16-bit load immediate | |
1069 (define_peephole2 | |
1070 [(set (match_operand:SI 0 "low_register_operand" "") | |
1071 (match_operand:SI 1 "const_int_operand" ""))] | |
1072 "TARGET_THUMB2 | |
1073 && peep2_regno_dead_p(0, CC_REGNUM) | |
1074 && (unsigned HOST_WIDE_INT) INTVAL(operands[1]) < 256" | |
1075 [(parallel | |
1076 [(set (match_dup 0) | |
1077 (match_dup 1)) | |
1078 (clobber (reg:CC CC_REGNUM))])] | |
1079 "" | |
1080 ) | |
1081 | |
1082 (define_insn "*thumb2_movsi_shortim" | |
1083 [(set (match_operand:SI 0 "low_register_operand" "=l") | |
1084 (match_operand:SI 1 "const_int_operand" "I")) | |
1085 (clobber (reg:CC CC_REGNUM))] | |
1086 "TARGET_THUMB2 && reload_completed" | |
1087 "mov%!\t%0, %1" | |
1088 [(set_attr "predicable" "yes") | |
1089 (set_attr "length" "2")] | |
1090 ) | |
1091 | |
1092 ;; 16-bit add/sub immediate | |
1093 (define_peephole2 | |
1094 [(set (match_operand:SI 0 "low_register_operand" "") | |
1095 (plus:SI (match_operand:SI 1 "low_register_operand" "") | |
1096 (match_operand:SI 2 "const_int_operand" "")))] | |
1097 "TARGET_THUMB2 | |
1098 && peep2_regno_dead_p(0, CC_REGNUM) | |
1099 && ((rtx_equal_p(operands[0], operands[1]) | |
1100 && INTVAL(operands[2]) > -256 && INTVAL(operands[2]) < 256) | |
1101 || (INTVAL(operands[2]) > -8 && INTVAL(operands[2]) < 8))" | |
1102 [(parallel | |
1103 [(set (match_dup 0) | |
1104 (plus:SI (match_dup 1) | |
1105 (match_dup 2))) | |
1106 (clobber (reg:CC CC_REGNUM))])] | |
1107 "" | |
1108 ) | |
1109 | |
1110 (define_insn "*thumb2_addsi_short" | |
1111 [(set (match_operand:SI 0 "low_register_operand" "=l") | |
1112 (plus:SI (match_operand:SI 1 "low_register_operand" "l") | |
1113 (match_operand:SI 2 "low_reg_or_int_operand" "lIL"))) | |
1114 (clobber (reg:CC CC_REGNUM))] | |
1115 "TARGET_THUMB2 && reload_completed" | |
1116 "* | |
1117 HOST_WIDE_INT val; | |
1118 | |
1119 if (GET_CODE (operands[2]) == CONST_INT) | |
1120 val = INTVAL(operands[2]); | |
1121 else | |
1122 val = 0; | |
1123 | |
1124 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */ | |
1125 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val))) | |
1126 return \"sub%!\\t%0, %1, #%n2\"; | |
1127 else | |
1128 return \"add%!\\t%0, %1, %2\"; | |
1129 " | |
1130 [(set_attr "predicable" "yes") | |
1131 (set_attr "length" "2")] | |
1132 ) | |
1133 | |
1134 (define_insn "divsi3" | |
1135 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
1136 (div:SI (match_operand:SI 1 "s_register_operand" "r") | |
1137 (match_operand:SI 2 "s_register_operand" "r")))] | |
1138 "TARGET_THUMB2 && arm_arch_hwdiv" | |
1139 "sdiv%?\t%0, %1, %2" | |
1140 [(set_attr "predicable" "yes") | |
1141 (set_attr "insn" "sdiv")] | |
1142 ) | |
1143 | |
1144 (define_insn "udivsi3" | |
1145 [(set (match_operand:SI 0 "s_register_operand" "=r") | |
1146 (udiv:SI (match_operand:SI 1 "s_register_operand" "r") | |
1147 (match_operand:SI 2 "s_register_operand" "r")))] | |
1148 "TARGET_THUMB2 && arm_arch_hwdiv" | |
1149 "udiv%?\t%0, %1, %2" | |
1150 [(set_attr "predicable" "yes") | |
1151 (set_attr "insn" "udiv")] | |
1152 ) | |
1153 | |
1154 (define_insn "*thumb2_subsi_short" | |
1155 [(set (match_operand:SI 0 "low_register_operand" "=l") | |
1156 (minus:SI (match_operand:SI 1 "low_register_operand" "l") | |
1157 (match_operand:SI 2 "low_register_operand" "l"))) | |
1158 (clobber (reg:CC CC_REGNUM))] | |
1159 "TARGET_THUMB2 && reload_completed" | |
1160 "sub%!\\t%0, %1, %2" | |
1161 [(set_attr "predicable" "yes") | |
1162 (set_attr "length" "2")] | |
1163 ) | |
1164 | |
1165 (define_insn "*thumb2_cbz" | |
1166 [(set (pc) (if_then_else | |
1167 (eq (match_operand:SI 0 "s_register_operand" "l,?r") | |
1168 (const_int 0)) | |
1169 (label_ref (match_operand 1 "" "")) | |
1170 (pc))) | |
1171 (clobber (reg:CC CC_REGNUM))] | |
1172 "TARGET_THUMB2" | |
1173 "* | |
1174 if (get_attr_length (insn) == 2 && which_alternative == 0) | |
1175 return \"cbz\\t%0, %l1\"; | |
1176 else | |
1177 return \"cmp\\t%0, #0\;beq\\t%l1\"; | |
1178 " | |
1179 [(set (attr "length") | |
1180 (if_then_else | |
1181 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) | |
1182 (le (minus (match_dup 1) (pc)) (const_int 128))) | |
1183 (const_int 2) | |
1184 (const_int 8)))] | |
1185 ) | |
1186 | |
1187 (define_insn "*thumb2_cbnz" | |
1188 [(set (pc) (if_then_else | |
1189 (ne (match_operand:SI 0 "s_register_operand" "l,?r") | |
1190 (const_int 0)) | |
1191 (label_ref (match_operand 1 "" "")) | |
1192 (pc))) | |
1193 (clobber (reg:CC CC_REGNUM))] | |
1194 "TARGET_THUMB2" | |
1195 "* | |
1196 if (get_attr_length (insn) == 2 && which_alternative == 0) | |
1197 return \"cbnz\\t%0, %l1\"; | |
1198 else | |
1199 return \"cmp\\t%0, #0\;bne\\t%l1\"; | |
1200 " | |
1201 [(set (attr "length") | |
1202 (if_then_else | |
1203 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) | |
1204 (le (minus (match_dup 1) (pc)) (const_int 128))) | |
1205 (const_int 2) | |
1206 (const_int 8)))] | |
1207 ) | |
1208 | |
1209 ;; 16-bit complement | |
1210 (define_peephole2 | |
1211 [(set (match_operand:SI 0 "low_register_operand" "") | |
1212 (not:SI (match_operand:SI 1 "low_register_operand" "")))] | |
1213 "TARGET_THUMB2 | |
1214 && peep2_regno_dead_p(0, CC_REGNUM)" | |
1215 [(parallel | |
1216 [(set (match_dup 0) | |
1217 (not:SI (match_dup 1))) | |
1218 (clobber (reg:CC CC_REGNUM))])] | |
1219 "" | |
1220 ) | |
1221 | |
1222 (define_insn "*thumb2_one_cmplsi2_short" | |
1223 [(set (match_operand:SI 0 "low_register_operand" "=l") | |
1224 (not:SI (match_operand:SI 1 "low_register_operand" "l"))) | |
1225 (clobber (reg:CC CC_REGNUM))] | |
1226 "TARGET_THUMB2 && reload_completed" | |
1227 "mvn%!\t%0, %1" | |
1228 [(set_attr "predicable" "yes") | |
1229 (set_attr "length" "2")] | |
1230 ) | |
1231 | |
1232 ;; 16-bit negate | |
1233 (define_peephole2 | |
1234 [(set (match_operand:SI 0 "low_register_operand" "") | |
1235 (neg:SI (match_operand:SI 1 "low_register_operand" "")))] | |
1236 "TARGET_THUMB2 | |
1237 && peep2_regno_dead_p(0, CC_REGNUM)" | |
1238 [(parallel | |
1239 [(set (match_dup 0) | |
1240 (neg:SI (match_dup 1))) | |
1241 (clobber (reg:CC CC_REGNUM))])] | |
1242 "" | |
1243 ) | |
1244 | |
1245 (define_insn "*thumb2_negsi2_short" | |
1246 [(set (match_operand:SI 0 "low_register_operand" "=l") | |
1247 (neg:SI (match_operand:SI 1 "low_register_operand" "l"))) | |
1248 (clobber (reg:CC CC_REGNUM))] | |
1249 "TARGET_THUMB2 && reload_completed" | |
1250 "neg%!\t%0, %1" | |
1251 [(set_attr "predicable" "yes") | |
1252 (set_attr "length" "2")] | |
1253 ) | |
1254 |